我想等待Task <T>完成一些特殊规则:如果在X毫秒后它还没有完成,我想向用户显示一条消息.如果它在Y毫秒后没有完成,我想自动请求取消.
我可以使用Task.ContinueWith异步等待任务完成(即安排在任务完成时执行的操作),但这不允许指定超时.我可以使用Task.Wait同步等待任务完成超时,但这会阻止我的线程.如何异步等待任务完成超时?
等待故障任务(具有异常集的任务)时,await
将重新抛出存储的异常.如果存储的异常是a AggregateException
,它将重新抛出第一个并丢弃其余的异常.
我们如何使用await
并同时抛出原件AggregateException
以便我们不会意外丢失错误信息?
注意,当然可以考虑使用hacky解决方案(例如,试一试await
,然后调用Task.Wait
).我真的希望找到一个干净的解决方案.这里最好的做法是什么?
我想过使用自定义awaiter,但内置TaskAwaiter
包含很多魔法,我不知道如何完全重现.它调用TPL类型的内部API.我也不想重现所有这些.
如果你想玩它,这是一个简短的repro:
static void Main()
{
Run().Wait();
}
static async Task Run()
{
Task[] tasks = new[] { CreateTask("ex1"), CreateTask("ex2") };
await Task.WhenAll(tasks);
}
static Task CreateTask(string message)
{
return Task.Factory.StartNew(() => { throw new Exception(message); });
}
Run Code Online (Sandbox Code Playgroud)
只抛出两个例外中的一个Run
.
请注意,Stack Overflow上的其他问题无法解决此特定问题.建议重复时请小心.
我在这里阅读更多关于异步的信息:http://msdn.microsoft.com/en-us/library/hh873173( v = vs1010).aspx
通过这个例子:
Task<bool> [] recommendations = …;
while(recommendations.Count > 0)
{
Task<bool> recommendation = await Task.WhenAny(recommendations);
try
{
if (await recommendation) BuyStock(symbol);
break;
}
catch(WebException exc)
{
recommendations.Remove(recommendation);
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道,如果我已经在等待,Task.WhenAny
为什么我需要再次在try块中等待?
如果我已经这样做了:Task<bool> recommendation = await Task.WhenAny(recommendations);
为什么这样做:if (await recommendation) BuyStock(symbol);
我们托管一个大容量的 WCF Web 服务,其逻辑上具有以下代码:
void WcfApiMethod()
{
// logic
// invoke other tasks which are critical
var mainTask = Task.Factory.StartNew(() => { /* important task */ });
mainTask.Wait();
// invoke background task which is not critical
var backgroundTask = Task.Factory.StartNew(() => { /* some low-priority background action (not entirely async) */ });
// no need to wait, as this task is best effort. Fire and forget
// other logic
}
// other APIs
Run Code Online (Sandbox Code Playgroud)
现在的问题是,在某些情况下,低优先级后台任务可能需要更长的时间(约 30 秒),例如,检测 SQL 连接问题、DB …