【问题标题】:Task.WhenAny does not exist when task is finished任务完成时Task.WhenAny不存在
【发布时间】:2020-03-30 16:50:54
【问题描述】:

我们有一个让后台作业保持运行的逻辑,可以是每 20 分钟一次,也可以是在某项任务完成后继续运行。

我想要做的简化版本如下:

控制我们是否需要退出的任务:

private static TaskCompletionSource<bool> forceSyncTask = new TaskCompletionSource<bool>();

后台工作:

     Task.Factory.StartNew(
                async () =>
                {
                    do
                    {
                        await Dosomething();
                        await Task.WhenAny(Task.Delay(TimeSpan.FromMinutes(20)), forceSyncTask.Task);

                        // Always reset the force sync property
                        forceSyncTask = new TaskCompletionSource<bool>();
                    }
                    while (true);
                });

然后每次有通知来,我运行以下强制退出Task.WhenAny

    if (!forceSyncTask.Task.IsCompleted)
    {
        forceSyncTask.TrySetResult(true);
    }

我在开发箱中对其进行了测试,并且可以正常工作。但是,在我将它部署到我们的产品环境中的 webervice 之后, 即使我成功 SetResult(我有日志知道 TrySetResult 是否返回 true),Task.WhenAny 也不会按预期退出。

有人知道为什么吗?

【问题讨论】:

  • forceSyncTask 字段可能存在竞争条件,该字段由多个线程访问而无需同步。附带说明一下,如果您打算每 20 分钟运行一次作业,则应在等待 Dosomething 之前创建 Task.Delay 任务,然后再创建 await
  • 您的条件是if (forceSyncTask.Task.IsCompleted)。不应该是相反的吗? if (!forceSyncTask.Task.IsCompleted),否则只有当它已经完成时你才完成任务。无论如何,TrySetResult 在内部实现了这个检查,所以你可以删除整个条件
  • 对不起,我会更新那部分。在 prod 中情况正好相反。

标签: c# multithreading async-await static


【解决方案1】:

首先,我建议您使用已建立的解决方案来暂停异步方法,例如Stephen Toub's PauseTokenPauseToken from my AsyncEx library。目前代码中有一些危险信号:StartNew with an async delegate and without a TaskSchedulerTaskCompletionSource&lt;T&gt; 在没有 RunContinuationsAsynchronously 选项的情况下使用。最好坚持使用更高级别的构造(分别为Task.RunPauseToken),因为低级构造上有很多尖角。

至于到底是什么问题,这很难说清楚,尤其是因为您(和我们)无法在本地重现它。这是我的主要猜测:

  1. 您遇到了由 continuations run synchronously if possible 引起的问题 - 即 TrySetResult 最终直接调用了 Task.WhenAny 中的某些代码。
  2. 您的生产服务器遇到线程耗尽问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-19
    • 1970-01-01
    • 2019-04-08
    • 1970-01-01
    • 2012-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多