所以我有一个延续定义:
var task = _httpClient.SendAsync(request, cts.Token);
task.ContinueWith(i => { /* TODO: log */ },
TaskContinuationOptions.OnlyOnCanceled);
var response = await task.ConfigureAwait(false);
我在ContinueWith
行收到编译器警告:
由于未等待此调用,因此在完成调用之前会继续执行当前方法。考虑应用“等待”#39;运算符到调用的结果。
但是,正如您所看到的,我将await
应用于响应。
当包含此代码的方法退出时,我会得到NullReferenceException
:
at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext)
at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
at System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state)
at System.Web.LegacyAspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state)
at System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task& currentTask)
我的问题是:如何正确使用任务延续和ConfigureAwait(false)
?
答案 0 :(得分:1)
ContinueWith
是您在async-await
之前使用的内容。 Await自动将方法的其余部分注册为继续,因此您不需要这样做。要使用await
实现您想要的效果,您可以使用CancellationToken
注册回调,以便在取消时进行记录。
CancellationTokenSource cts = new CancellationTokenSource();
cts.Token.Register(() => /* TODO: log */);
var task = _httpClient.SendAsync(request, cts.Token).ConfigureAwait(false);
ConfigureAwait(false)
只是告诉编译器不要切换回捕获的同步上下文。如果您使用ContinueWith
,则可以提供TaskContinutationOptions.ExecuteSynchronously
。
var task = _httpClient.SendAsync(request, cts.Token);
return task.ContinueWith(i => { /* TODO: log */ },
TaskContinuationOptions.OnlyOnCanceled | TaskContinutationOptions.ExecuteSynchronously);
答案 1 :(得分:0)
事实证明,我遗漏了一些重要信息:如果<{em>你<{em>> await
导致异常的方法,异常将按照正常冒充你的代码。所以,我所要做的就是:
try
{
await queue.AddMessageAsync(message).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
throw new Exception(string.Format("Unable to push message to queue {0}", queueName));
}
由于await
是继续的语法糖,因此将继续例外。