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



我们在 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 来限制任务的数量吗?

我通常不鼓励在与请求无关的 ASP.NET 中执行代码。但是,如果它是作为独立工作者精心编写的(听起来确实如此),那么您可以使用我博客中的BackgroundTaskManager类型。

BackgroundTaskManager理解同步和异步任务,并且这些任务已注册到 ASP.NET 运行时,以最大程度地减少回收意外终止它们的可能性。此外,该类型还公开一个名为 BackgroundTaskManager.ShutdownCancellationTokenPollingQueueAndWorkAsync可以使用该来检测何时应干净退出。

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

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

然后,您应该检查线程本身中的"_continue",以便在取消工作时它们可以干净地退出。

最新更新