我有一個C#控制臺應用程式,其中有許多異步任務。其中一個任務拋出了一個例外。然而,我了解到,主機代碼沒有按照預期處理這種情況。為了了解發生了什么,我決定做一個測驗。這個測驗的目的是創建一個Task,它將異步運行,但是,故意拋出一個例外。我想看看回傳的內容是否與主機代碼所期望的一致。
令我驚訝的是,Task物件的IsCompletedSuccessfully屬性為true,IsFaulted屬性為false。然而,我期望IsCompletedSuccessfully是false,IsFaulted是true。代碼看起來像下面這樣:
[]
public void Repro()
{
var task = new Task(async ( ) => {
var operand1 = 2;
var operand2 = 0;
var result = operand1 / operand2。
Thread.Sleep(250)。
await Task.CompletedTask。
});
task.RunSynchronously()。
Console.WriteLine($"Cancelled: {task.IsCanceled}, Completed: {task.IsCompleted}, 成功完成。{task.IsCompletedSuccessfully}, Faulted: {task.IsFaulted}")。)
if (task.Exception != null)
{
Console.WriteLine("There was an exception")。
}
Assert.Equal(false, task.IsCompletedSuccessfully)。
Assert.Equal(true, task.IsFaulted);
}
為什么/怎么會成功完成這個任務?為什么它沒有出現故障?我以為它會拋出一個除以0的例外。
謝謝你。
謝謝你。
uj5u.com熱心網友回復:
沒有任何Task建構式需要一個Func<Task>:只有overloads需要一個Action或Action<object>。
因此,當你寫new Task(async () => ...)時,這里的async lambda需要編譯為async void方法。
注意void:沒有辦法將Task傳回給呼叫者,這意味著用new Task(...)構造的Task只有在lambda直接拋出一個例外的情況下才能知道。然而,由于lambda是async void,它不會向它的呼叫者拋出例外!但是它將重新拋出例外。然而,它將在執行緒池中重新拋出這些例外,這將使你的應用程式崩潰。
uj5u.com熱心網友回復:
@canton7的回答對話了你所看到的行為,但他們好心地沒有說我要說的話,那就是 "你做錯了"。將Thread.Sleep與async/await混合,同步執行異步代碼...為什么?只是,為什么?
下面的作業與預期完全一致,因為它沒有試圖做一些毫無意義的隨機事情:
[Fact]
public async void _Repro()
{
var task = Task.Run(async ( ) =>
{
var operand1 = 2;
var operand2 = 0;
var result = operand1 / operand2。
await Task.Delay(250)。
});
await Assert.ThrowsAsync<DivideByZeroException>(async () => await task) 。
Console.WriteLine($"Cancelled: {task.IsCanceled}, Completed: {task.IsCompleted}, 成功完成。{task.IsCompletedSuccessfully}, Faulted: {task.IsFaulted}")。)
if (task.Exception != null)
{
Console.WriteLine("There was an exception")。
}
Assert.False(task.IsCompletedSuccessfully)。
Assert.True(task.IsFaulted);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/318020.html
標籤:
上一篇:為什么執行沒有停止在await(async/awaitJS)?
下一篇:為什么在使用ConstBufferSequence緩沖區的async_send_some的呼叫者中沒有一個"游標"?
