wp8的任务队列?
在wp8中排列复杂任务的正确方法是什么?wp8的任务队列?
任务由以下部分组成:
- 显示一个
ProgressIndicator
通过更新模型变量 - 提取或将数据存储到WCF服务(
UploadStringAsync
) - 更新潜在数据绑定模型,其结果从
UploadStringCompleted
。 - 通过更新变量
目前,我已经工作了一类拥有命令对象的队列,在运行时添加的项目已启动一个单独的线程模型隐藏ProgressIndicator
如果它尚未运行。
但是,我有等待代码停止运行的任务或子任务的问题。
此前我已经使用异步等待,但行为的几个级别变得越来越难以预测。
我想要的是主线程能够创建和排队命令对象。 命令对象应该一次运行一个,直到前一个完全结束才启动一个新对象。 命令对象应该能够使用调度程序访问主线程(如果有必要)。
如果您使用的是async
/await
,则不需要另一个线程(因为您没有CPU绑定处理)。
就你而言,这听起来像你只需要一个异步委托队列。异步委托的自然类型是Func<Task>
(没有返回值)或Func<Task<T>>
(具有返回值)。不幸的是,这个小技巧在这一点上并不为人所知。
因此,申报异步委托队列:
private readonly Queue<Func<Task>> queue = new Queue<Func<Task>>();
然后你就可以有一个单一的“*”的任务,只是(异步)处理队列:
private Task queueProcessor;
的queueProcessor
只要没有更多的物品,可以是null
。只要它不是null
,它会代表这个方法:然后
private async Task ProcessQueue()
{
try
{
while (queue.Count != 0)
{
Func<Task> 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<Task> command)
{
queue.Enqueue(command);
if (queueProcessor == null)
queueProcessor = ProcessQueue();
}
,我有异常处理设置是这样的:任何排队抛出异常的命令将导致队列处理器停止处理(具有相同的异常)。这可能不是您的应用程序的最佳行为。
您可以使用这样的(带有一个lambda或实际的方法,当然):
Enqueue(async() =>
{
ShowProgressIndicator = true;
ModelData = await myProxy.DownloadStringTaskAsync();
ShowProgressIndicator = false;
});
注意使用DownloadStringTaskAsync
。如果你write TAP wrappers for your EAP members,你的async
代码将更“自然”(即更简单)。
这是非常复杂,我建议你把它变成一个单独的类,但你要决定如何处理(和面)错误第一。
我想知道会发生什么,如果我将足够的暂停两次调用Enqueue,以便第一个命令已经出队并等待。 –
好抓! Enqueue中的检查应该用于'queueProcessor',而不是'queue.Count'。我已经更新了答案中的代码。 –
我试图用这种类型的工作队列实现暂停/恢复,这样在应用程序关闭时我可以暂停并坚持数据库,或者让用户有机会等待,并因此恢复处理。 虽然让它工作起来很麻烦。取消是命中与遗漏,并且恢复_queueprocessor = ProcessQueue()不像Enqueue()中那样工作。 很高兴听到别人会怎么做呢? – FrugalTPH
'BlockingCollection'? – I4V