我在任務中有一個無限循環。在某些情況下,該任務會引發異常並終止。考慮下面的代碼片段。如何從ContinueWith傳播異常到無限循環任務的調用上下文
private async void Button_Click(object sender, RoutedEventArgs e)
{
try
{
int x = await FirstTask();
window.Title = "FirstTask completed with " + x.ToString();
}
catch (ArgumentException ex)
{
textbox.Text = ex.Message;
}
}
public async Task<int> FirstTask()
{
Task<int> secondTask;
int result;
secondTask = SecondTask();
textbox.Text = "Awaiting SecondTask result";
result = await secondTask;
textbox.Text = result;
secondTask.ContinueWith(async (Task t) =>
{
var thirdTask = ThirdTask();
thirdTask.ContinueWith(
async (m) =>
await Task.Run(() =>
{
throw thirdTask.Exception.InnerException;
}),
TaskContinuationOptions.OnlyOnFaulted);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
return 5;
}
public async Task<int> SecondTask()
{
await Task.Delay(1500);
return 8;
}
public async Task ThirdTask()
{
while (true)
{
await Task.Delay(500);
throw new ArgumentException("thirdException");
}
}
我的問題在於無法將從ThirdTask拋出的異常傳播到Button_Click事件。很明顯,等待它不是一個選項,因爲它是一個持續的無限操作(這只是簡化爲快速失敗)。然而,對於等待重新拋出異常的「短」任務,如果它僅在ThirdTask失敗時才觸發,則沒有問題。請注意,我對ThirdTask的行爲沒有興趣,除非它失敗了,也就是說,我可以等待事件處理程序中的FirstTask。
實驗表明,即使是最簡單的示例也不會從ContinueWith塊傳播異常。
private async void Button_Click(object sender, RoutedEventArgs e)
{
try
{
Task task = Task.Run(async() => { await Task.Delay(1000); });
task.ContinueWith((t) => { throw new ArgumentException("test"); }, TaskContinuationOptions.OnlyOnRanToCompletion);
}
catch (ArgumentException ex)
{
textbox.Text = ex.Message;
}
}
那麼,我該如何從傳播到ContinueWith調用上下文的異常,因爲,拋出它具有一個無限循環的任務,這使我的等待呢?
我試圖解決的問題有兩個:首先,我需要初始化一個資源(FirstTask),爲了做到這一點,我首先需要獲取它(SecondTask),然後開始一個(ThirdTask),最後,資源的初始化(FirstTask)返回一個值,表示資源的狀態,它不依賴於進程(ThirdTask)。進程(ThirdTask)重複調用另一個任務(在本例中爲Task.Delay)並對其執行一些工作,但可能會失敗。在這種情況下,它會拋出一個需要處理的異常。
第二部分是第二個代碼示例的一般情況,說明如何從ContinueWith中引發異常以便由調用上下文處理。
其實,等待*爲*解決方案和無限循環不會造成任何影響。一個異常*會*中斷循環,因此等待從'ContinueWith'返回的任務將捕獲異常。事實上,你甚至不需要'ContinueWith',你可以'在適當的excetion處理塊中等待ThirdTask()'。 'await'也會解開拋出的異常,所以你會得到最初的'ArgumentException' –
爲什麼複雜的代碼和'ContinueWith'?你試圖解決什麼實際問題? '等待SecondTask();等待ThirdTask();'應該足夠了,既可以在'SecondTask()'*之後啓動'ThirdTask()',也可以傳播任何異常 –
@PanagiotisKanavos不會等待ThirdTask在那裏阻止調用方法ThirdTask完成(在我的情況下最終是按鈕點擊處理程序)?如果沒有拋出異常,那將是永遠的,這是不希望的。例外情況不應該經常發生,但如果發生,我應該能夠處理它。複雜的代碼被簡化以強調問題。每個任務都有所作爲,所以這只是程序結構的一個大綱。 – user3209815