为什么我的延迟任务没有触发Task.WaitAny()

时间:2018-10-31 21:18:59

标签: c# .net task-parallel-library

所以我有以下内容:

if (await Task.WhenAny(myLongRunningTask, Task.Delay(9000)) != myLongRunnnigTask && !myLongRunningTask.IsFaulted)
{
    Console.WriteLine("TimedOut");
}
else
{
    Console.WriteLine("Completed");
}

当我完成任务时,似乎工作正常;但是,如果我从不完成长时间运行的任务,那么它将挂起,而不是在9秒后超时。甚至可以确定是否通过了错误的测试。

(注意:实际代码不只是命令行编写;它甚至没有进入作用域;尽管我也尝试过仅命令行编写...没有变化。)

但是在LinqPad中做与我完全相同的事情:

async void Main()
{
    var Other = Task.Factory.StartNew(() => { Thread.Sleep(15000); });
    if(await Task.WhenAny(Other, Task.Delay(4000)) != Other && !Other.IsFaulted) "TimedOut".Dump();
    else "Completed".Dump();

    Other = Task.Factory.StartNew(() => { Thread.Sleep(1000); });
    if(await Task.WhenAny(Other, Task.Delay(4000)) != Other && !Other.IsFaulted) "TimedOut".Dump();
    else "Completed".Dump();
}

高兴地写了TimedOut然后完成。

第一个代码部分位于一个巨大的模块中。但是我看不到它会对这种奇怪的行为产生什么副作用……我可能会缺少什么?

注意接受的答案:

这里的问题是,这可能会产生什么副作用。 @Douglas的答案表明影响我的代码的副作用。那不一定解决问题。只是告诉您问题所在。不过,他很有帮助地添加了评论,并提供了指向文章的链接,该链接确实可帮助您修复该问题。

2 个答案:

答案 0 :(得分:0)

如果您从同步上下文中阻止该异步方法,而该同步上下文在原始线程(例如WPF或WinForms UI)上执行延续,则可能会发生这种情况。尝试添加ConfigureAwait(false)并检查是否避免了挂起:

var readyTask = await Task.WhenAny(myLongRunningTask, Task.Delay(9000)).ConfigureAwait(false);
if (readyTask != myLongRunnnigTask && !myLongRunningTask.IsFaulted)
{
    Console.WriteLine("TimedOut");
}
else
{
    Console.WriteLine("Completed");
}

答案 1 :(得分:-2)

  

但是我看不出有什么可能会对这种奇怪的行为产生副作用...

您的longRunningTask可能被分配了以下方法的返回值:

private static Task NewMethod()
{
    Thread.Sleep(11000);
    return Task.CompletedTask;
}

然后再这样:

var myLongRunningTask = NewMethod();

因此,当您到达var readyTask = await行时,已经已经发生了11秒的睡眠(“长时间运行的任务”)(因为NewMethod不同步) ,因此Task.WhenAny立即返回(因为longRunningTask完成)。