如何将这个长期运行的后台任务转换为异步/等待?

时间:2019-05-29 10:58:30

标签: c# async-await

我有一些代码,可以通过心跳启动长期运行的后台任务。正在将应用程序更新为使用异步/等待,并且在更新此代码以遵循套件时遇到问题。这是大致的代码:

private void StartBackgroundTasks(CancellationTokenSource cancelTokenSrc)
{
    void TaskAction()
    {
        DoWork();
    }

    void HeartbeatAction()
    {
        var task = TaskFactory.CreateAndStartLongRunningTask(
            TaskAction, cancelTokenSrc.Token);

        while (true)
        {
            // checks Task.Status to figure out when to stop
            if (!TryPerformHeartbeat(task)) break;

            Task.Delay(TimeSpan.FromSeconds(20)).Wait();
        }
    }

    TaskFactory.CreateAndStartLongRunningTask(HeartbeatAction);
}

这是长时间运行的任务的启动方式:

internal static class TaskFactory
{
    internal static Task CreateAndStartLongRunningTask(
        Action action, CancellationToken? token = null)
    {
        return Task.Factory.StartNew(
            action,
            token ?? CancellationToken.None,
            TaskCreationOptions.LongRunning,
            TaskScheduler.Default);
    }
}

据我了解,我需要:

  • Func<Task>传递给CreateAndStartLongRunningTask
  • StartNew改为async () => await taskFunc(),而不是action
  • 根据需要通过方法签名添加异步/唤醒

使此代码在后台线程上运行并允许使用异步/等待模式的正确方法是什么?

2 个答案:

答案 0 :(得分:3)

简而言之,除非您特别需要,否则不应使用Task.Factory.StartNewTaskCreationOptions.LongRunning。只需像这样使用Task.Run

var task = Task.Run(async () =>
{
    while (true)
    {
        await TryPerformHeartbeat();
        await Task.Delay(TimeSpan.FromSeconds(20));

    }
}, token);

这两篇文章有助于解释原因: http://blog.i3arnon.com/2015/07/02/task-run-long-running/https://sergeyteplyakov.github.io/Blog/async/2019/05/21/The-Dangers-of-Task.Factory.StartNew.html

答案 1 :(得分:0)

  

正在将应用程序更新为使用异步/等待

这并不意味着一切都应该变得异步。是否是候选者取决于它如何与呼叫者和被呼叫者交互。您没有发布任何内容。

您可以(应该)保持原样。

哦,总有一个带有延迟的循环是可疑的。为什么不在计时器上运行它呢?