所以我有以下内容:
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的答案表明影响我的代码的副作用。那不一定解决问题。只是告诉您问题所在。不过,他很有帮助地添加了评论,并提供了指向文章的链接,该链接确实可帮助您修复该问题。
答案 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
完成)。