為什么UseEventsFail在下面的代碼中拋出?難道是我在不等待最后一個MoveNextAsync()任務的情況下處理了異步列舉器?這個例子是我真實程式的簡化復制,所以我需要處理異步列舉器來釋放它的資源。并且Task.CompletedTask通常Task.Delay()用作UseEvents(). 如果列舉器任務在超時任務之前完成,則不會引發例外。
例外的堆疊跟蹤:
at Program.<<<Main>$>g__GenerateEvents|0_3>d.System.IAsyncDisposable.DisposeAsync()
代碼:
// All these are ok
await GenerateEvents().GetAsyncEnumerator().DisposeAsync();
await using var enu = GenerateEvents().GetAsyncEnumerator();
await UseEvents();
await UseEvents2();
// This fail
await UseEventsFail();
async Task UseEvents()
{
await using var enu = GenerateEvents().GetAsyncEnumerator();
await Task.WhenAny(enu.MoveNextAsync().AsTask());
}
async Task UseEvents2()
{
var enu = GenerateEvents().GetAsyncEnumerator();
await Task.WhenAny(enu.MoveNextAsync().AsTask(), Task.CompletedTask);
}
async Task UseEventsFail()
{
await using var enu = GenerateEvents().GetAsyncEnumerator();
await Task.WhenAny(enu.MoveNextAsync().AsTask(), Task.CompletedTask);
}
async IAsyncEnumerable<bool> GenerateEvents()
{
while (true) {
await Task.Delay(1000);
yield return true;
}
}
uj5u.com熱心網友回復:
從 MSDN 文章Iterating with Async Enumerables in C# 8 by Stephen Toub:
很明顯,一個
MoveNextAsync呼叫發生在與前一個或后續MoveNextAsync呼叫不同的執行緒上是可以的;畢竟,實作可能會等待一個任務并在其他地方繼續執行。然而,這并不意味著MoveNextAsync是“執行緒安全的”——遠非如此。在給定的異步列舉器上,MoveNextAsync絕不能并發呼叫,這意味著MoveNextAsync在上一次呼叫完成之前,不應在給定的列舉器上再次呼叫它。類似地,DisposeAsync不應在同一列舉器中的任一個MoveNextAsync或DisposeAsync同一列舉器仍在運行時呼叫迭代器。
所以,不,IAsyncEnumerator<T>s 不支持并發。對于IEnumerator<T>s也是如此。Dispose當 aMoveNext在另一個執行緒上運行時,您不能從一個執行緒呼叫。列舉一般(同步或異步)不是執行緒安全的程序,必須同步。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/349159.html
上一篇:c#autopropertyset方法和OnPropertyChanged方法未執行
下一篇:防止.Net服務重啟時資料丟失
