顶级工作者方法中的异步模式

时间:2013-10-12 01:33:34

标签: c# multithreading asynchronous task-parallel-library async-await

我们在Web角色中有一些工作线程。它是在OnStart方法

中创建的
Task.Factory.StartNew(() => DoWorkAsync(), TaskCreationOptions.LongRunning);

然后DoWorkAsync方法将继续轮询队列并做一些耗时的工作。实际工作需要几分钟时间,因为它提交查询作业并等待结果返回。这些函数采用async模式。实现顶级DoWorkAsync方法的正确方法是什么?如果我执行以下操作,那么它在此处是一种阻塞,并且只调用一个PollingQueueAndWorkAsync()

public async void DoWorkAsync()
{
  while (_continue)
  {
    await PollingQueueAndWorkAsync();
  }
}

或以下?它看起来不正确,因为它在不同的线程中继续运行该方法。

public async void DoWorkAsync()
{
  while (_continue)
  {
    Task.Run(() => PollingQueueAndWorkAsync());
  }
}

我正在尝试重构代码“一直异步”。但它应该如何以顶级工人方法结束呢?

[更新]

在尝试更多之后,这就是我所拥有的:

public async void DoWorkAsync()
{
  while (_continue)
  {
    Task.Run(async () => await PollingQueueAndWorkAsync());
  }
}

行为是我想要的,因为新消息不断添加到队列中,此循环可以处理与队列中的消息一样多的消息。但是在运行一段时间之后,它会抛出我们的内存异常。是因为它创造了太多的延续吗?所以我应该使用SemaphoreSlim来限制任务数量?

2 个答案:

答案 0 :(得分:2)

我通常不鼓励在ASP.NET中执行的代码与请求无关。但是,如果它是作为独立工作者仔细编写的(听起来像是这样),那么您可以使用我博客中的BackgroundTaskManager type

BackgroundTaskManager了解同步和异步任务,并且这些任务在ASP.NET运行时中注册,以最大限度地减少回收将意外终止它们的可能性。此外,该类型还会显示CancellationToken BackgroundTaskManager.Shutdown PollingQueueAndWorkAsync,{{1}}可以使用{{1}}来检测何时应该干净地退出。

答案 1 :(得分:0)

您应该像这样创建轮询线程:

public async void DoWorkAsync()
{
    await Task.Run(() => PollingQueueAndWorkAsync());
}

然后你应该检查线程本身内的'_continue',这样他们就可以在取消工作时干净利落地退出。