【问题标题】:Task queue for wp8?wp8的任务队列?
【发布时间】:2013-05-21 21:10:39
【问题描述】:

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

任务包括以下内容:

  1. 通过更新模型变量显示ProgressIndicator
  2. 获取数据或将数据存储到 wcf 服务 (UploadStringAsync)
  3. 使用来自UploadStringCompleted 的结果更新潜在的数据绑定模型。
  4. 通过更新模型变量隐藏ProgressIndicator

目前我一直在处理一个拥有命令对象队列的类,运行一个线程,如果它尚未运行,则在添加项目时启动该线程。

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

以前我使用过 async await,但在往下几个级别时,行为变得越来越不可预测。

我想要的是能够创建和排队命令对象的主线程。 命令对象应该一次运行一个,在前一个完全完成之前不要开始新的。 如果需要,命令对象应该能够使用调度程序访问主线程。

【问题讨论】:

  • BlockingCollection ?

标签: c# windows-phone-7 windows-phone-8 task dispatcher


【解决方案1】:

如果您使用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() 中那样工作。听听其他人会怎么做会很好吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-30
相关资源
最近更新 更多