wp8的任务队列?
在wp8中对复杂任务进行排队的正确方法是什么?
任务包括以下内容:
- 通过更新模型变量显示
ProgressIndicator
- 获取或存储数据到wcf服务(
UploadStringAsync
) - 使用
UploadStringCompleted
的结果更新潜在的数据绑定模型。 - 通过更新模型变量隐藏
ProgressIndicator
目前我一直在使用一个拥有命令对象队列的类,运行一个在添加项目时启动的线程(如果它尚未运行)。
但是,我有等待代码停止运行的任务或子任务的问题。
以前我曾经使用异步等待,但是行为的几个级别变得越来越难以预测。
我想要的是能够创建和排队命令对象的主线程。 命令对象应该一次运行一个,而不是在前一个完全完成之前启动一个新对象。 如果需要,命令对象应该能够使用调度程序访问主线程。
如果使用async
/ await
,则不需要另一个线程(因为您没有CPU绑定处理)。
在您的情况下,听起来您只需要一个异步委托队列。 异步委托的自然类型是Func
(没有返回值)或Func
(带有返回值)。 遗憾的是,这个小小的提示在这一点上并不为人所知。
因此,声明一个异步委托队列:
private readonly Queue> queue = new Queue>();
然后,您可以只有(异步)处理队列的单个“顶级”任务:
private Task queueProcessor;
只要没有更多项, queueProcessor
就可以为null
。 每当它不为null
,它将代表这种方法:
private async Task ProcessQueue() { try { while (queue.Count != 0) { Func command = queue.Dequeue(); try { await command(); } catch (Exception ex) { // Exceptions from your queued tasks will end up here. throw; } } } finally { queueProcessor = null; } }
您的Enqueue
方法将如下所示:
private void Enqueue(Func command) { queue.Enqueue(command); if (queueProcessor == null) queueProcessor = ProcessQueue(); }
现在,我有这样的exception处理设置:抛出exception的任何排队命令将导致队列处理器停止处理(具有相同的exception)。 这可能不是您的应用程序的最佳行为。
您可以像这样使用它(当然,使用lambda或实际方法):
Enqueue(async () => { ShowProgressIndicator = true; ModelData = await myProxy.DownloadStringTaskAsync(); ShowProgressIndicator = false; });
注意使用DownloadStringTaskAsync
。 如果您为EAP成员编写TAP包装器 ,您的async
代码将更“自然”(即,更简单)。
这非常复杂,我建议将它放入一个单独的类中,但是你想要先决定如何处理(和表面)错误。