wp8的任务队列?

问题描述:

在wp8中排列复杂任务的正确方法是什么?wp8的任务队列?

任务由以下部分组成:

  1. 显示一个ProgressIndicator通过更新模型变量
  2. 提取或将数据存储到WCF服务(UploadStringAsync
  3. 更新潜在数据绑定模型,其结果从UploadStringCompleted
  4. 通过更新变量

目前,我已经工作了一类拥有命令对象的队列,在运行时添加的项目已启动一个单独的线程模型隐藏ProgressIndicator如果它尚未运行。

但是,我有等待代码停止运行的任务或子任务的问题。

此前我已经使用异步等待,但行为的几个级别变得越来越难以预测。

我想要的是主线程能够创建和排队命令对象。 命令对象应该一次运行一个,直到前一个完全结束才启动一个新对象。 命令对象应该能够使用调度程序访问主线程(如果有必要)。

+0

'BlockingCollection'? – I4V

如果您使用的是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代码将更“自然”(即更简单)。

这是非常复杂,我建议你把它变成一个单独的类,但你要决定如何处理(和面)错误第一。

+0

我想知道会发生什么,如果我将足够的暂停两次调用Enqueue,以便第一个命令已经出队并等待。 –

+0

好抓! Enqueue中的检查应该用于'queueProcessor',而不是'queue.Count'。我已经更新了答案中的代码。 –

+0

我试图用这种类型的工作队列实现暂停/恢复,这样在应用程序关闭时我可以暂停并坚持数据库,或者让用户有机会等待,并因此恢复处理。 虽然让它工作起来很麻烦。取消是命中与遗漏,并且恢复_queueprocessor = ProcessQueue()不像Enqueue()中那样工作。 很高兴听到别人会怎么做呢? – FrugalTPH