2015-02-10 51 views
0

所以我有一個延續定義:任務延續的NullReferenceException

var task = _httpClient.SendAsync(request, cts.Token); 
task.ContinueWith(i => { /* TODO: log */ }, 
    TaskContinuationOptions.OnlyOnCanceled); 
var response = await task.ConfigureAwait(false); 

我上ContinueWith行編譯器警告:

因爲這個呼叫沒有等待,目前的方法執行之前繼續通話完成。考慮將「await」運算符應用於調用的結果。

但是,正如您所看到的,我將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

['ContinueWith'(https://msdn.microsoft.com/en-us/library/dd270696(V = vs.110)的.aspx)返回新任務,所以沒有什麼令人驚奇的警告... – 2015-02-10 03:54:00

+0

@AlexeiLevenkov有可能我在這裏錯過了一些重要的知識,因爲我從未真正嘗試過使用'ContinueWith'。任何想法如何正確使用它與異步/等待? – Haney 2015-02-10 04:04:14

回答

1

ContinueWith是您在async-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); 
0

事實證明,我錯過了一些重要信息:例外情況會冒泡到您的代碼每個正常如果await引起異常的方法。因此,所有我需要做的是這樣的:

try 
{ 
    await queue.AddMessageAsync(message).ConfigureAwait(false); 
} 
catch (OperationCanceledException) 
{ 
    throw new Exception(string.Format("Unable to push message to queue {0}", queueName)); 
} 

由於await是延續語法糖,除了會繼續它。

+1

對。 「任何有關如何正確使用ContinueWith和異步/等待?」的正確答案是*用'await'替換'ContinueWith'。 – 2015-02-10 14:00:47