3 回答

TA貢獻1775條經(jīng)驗 獲得超11個贊
異常僅在等待任務(wù)時傳播
您不能在不等待任務(wù)的情況下處理異常。異常僅在線程/任務(wù)內(nèi)傳播。因此,如果您不等待,異常只會停止任務(wù)。如果在您等待之前拋出異常,它將在您實際等待時傳播。
之前做所有的驗證,然后做異步工作。
所以,我建議你之前驗證:
ValidateId(id); // This will throw synchronously.
Task<Customer> customer = FetchCustomerAsync(id).ConfigureAwait(false);
DoSomethingElse();
return await customer.Name;
這是實現(xiàn)您想要的并行性的最佳方式。

TA貢獻1810條經(jīng)驗 獲得超4個贊
您是對的,該線程執(zhí)行異步函數(shù)直到它看到等待。事實上,你ArgumentOutofRangeException是由你調(diào)用的線程拋出的FetchCustmerNameAsync。即使它是同一個線程也不會得到異常的原因是因為當您await在函數(shù)內(nèi)部使用時,AsyncStateMachine構(gòu)建了 a 。它將所有代碼轉(zhuǎn)換為狀態(tài)機,但重要的部分是它如何處理異常??匆豢矗?/p>
這段代碼:
public void M() {
var t = DoWork(1);
}
public async Task DoWork(int amount)
{
if(amount == 1)
throw new ArgumentException();
await Task.Delay(1);
}
轉(zhuǎn)換為(我跳過了不重要的部分):
private void MoveNext()
{
int num = <>1__state;
try
{
TaskAwaiter awaiter;
if (num != 0)
{
if (amount == 1)
{
throw new ArgumentException();
}
awaiter = Task.Delay(1).GetAwaiter();
if (!awaiter.IsCompleted)
{
// Unimportant
}
}
else
{
// Unimportant
}
}
catch (Exception exception)
{
<>1__state = -2;
<>t__builder.SetException(exception); // Add exception to the task.
return;
}
<>1__state = -2;
<>t__builder.SetResult();
}
如果你跟著<>t__builder.SetException(exception);( AsyncMethodBuilder.SetException),你會發(fā)現(xiàn)它最終會調(diào)用task.TrySetException(exception);which 將異常添加到任務(wù)的 中exceptionHolder,可以通過Task.Exception屬性檢索。

TA貢獻1111條經(jīng)驗 獲得超0個贊
一個簡化的 MCVE :
static async Task Main(string[] args)
{
try
{
// enable 1 of these calls
var task = DoSomethingAsync();
// var task = DoSomethingTask();
Console.WriteLine("Still Ok");
await task;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static async Task DoSomethingAsync()
{
throw new NotImplementedException();
}
private static Task DoSomethingTask()
{
throw new NotImplementedException();
return Task.CompletedTask;
}
當您調(diào)用 DoSomethingAsync 時,您將看到“Still Ok”消息。
當您調(diào)用 DoSomethingTask 時,您將獲得您期望的行為:WriteLine 之前的立即異常。
- 3 回答
- 0 關(guān)注
- 432 瀏覽
添加回答
舉報