2017-04-02 35 views
1

我有下面的代碼片段處理Azure的通知中心推送通知:調試Task.WhenAny和推送通知

var alert = "{\"aps\":{\"alert\":\"" + message + "\"}}"; 

var task = AzurePushNotifications.Instance.Hub.SendAppleNativeNotificationAsync(alert, username); 

if (await Task.WhenAny(task, Task.Delay(500)) == task) 
{ 
    success = true; 
} 

偶爾,這將失敗 - 我想弄清楚,爲什麼?

Task.WhenAny一起運行的東西時獲取某些診斷信息的最佳方式是什麼?

我想知道是否拋出異常,或者如果超時已被擊中。

+1

這是什麼意思_fails_?如果超時,您只能通知500毫秒,這可能需要增加。如果你「等待」通知任務,它會引發異常?如果是這樣,請發佈這些細節。 – JSteward

+0

你爲什麼不直接等待任務; task.Wait();然後看TaskResult task.TaskResult? –

+0

@JSteward有時我會得到'success = false'。這要麼是因爲它沒有在500毫秒內完成,要麼是因爲引發了異常。我想知道其中哪一個正在發生。如果這是一個例外,我想知道什麼是例外。如果它需要> 500ms,我希望它失敗,但我想知道這就是它失敗的原因。如果沒有這些超時,推送通知有時會從字面上永遠消失。 – user666

回答

1

你基本上有三種可能性:

  1. Task.WhenAny(task, Task.Delay(500)) == task是假的。這意味着任務超時
  2. Task.WhenAny(task, Task.Delay(500)) == task是正確的。然後:
    • 如果t1.Status == TaskStatus.RanToCompletion,則任務成功運行
    • 否則,它取消或故障。檢查task.IsFaultedtask.Exception可以找到更多信息

如果需要> 500ms的,我希望它失敗了,但我想知道這是爲什麼會失敗

在這種情況下,唯一可以知道的是通知超時。由於任務尚未完成,因此記錄也不例外。如果要檢查其狀態它最終完成時,你可以鏈接一個延續:

task.ContinueWith(t => 
{ 
    // Log t.Exception 
}, TaskContinuationOptions.OnlyOnFaulted); 
+0

雖然邏輯是正確的,我不能容忍'ContinueWith' /'IsFaulted' /'Exception'的這種用法。你應該用'await'代替'ifit'中的'await task'。 –

+0

@StephenCleary如果我們使用await,那麼它首先會超時。這裏的邏輯是說:「好的,任務沒有及時回答,所以我把控制權交還給調用者,但我連續繼續知道當任務最終完成時發生了什麼」 –

1

我想知道如果任一個異常被拋出,或者如果超時被擊中。

你只需要觀察完成的任務,因爲這樣的:

var task = ...; 
if (await Task.WhenAny(task, Task.Delay(500)) == task) 
{ 
    await task; 
    success = true; 
} 

這將傳播的異常,讓你失敗的任務區分(一個會拋出異常),任務成功(success == true),並且任務超時(success == false)。

+0

謝謝斯蒂芬 - 你看到凱文的以上評論?我試圖避免請求超過500毫秒(即使這很荒謬),出於某種原因,這些對通知中心的調用永遠不會返回。我已經實施了一個慷慨的超時來解決這個問題,但我想知道 - 你會推薦什麼? – user666

+0

@ user666:我對Notification Hub沒有任何經驗,但是如果您確定自己沒有[阻止進一步調用堆棧](https://blog.stephencleary.com/2012/07/dont-block-on -async-code.html),那麼這將是一個Azure技術支持問題。 –

+0

我從一個普通的編碼角度詢問更多 - 如果我「等待」一件永遠不會回來的事情,那麼實現我上面列出的目標的最佳方法是什麼,並且在接受的答案中給出了評論?我覺得未來的讀者可以從這裏得到一個答案 - 好像是一個不是很差的異步/等待 – user666