【发布时间】: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