Yanıtlar:
En iyi uygulama, işlevi async void
yalnızca yangın ve unut yöntemiyse işaretlemektir, beklemek istiyorsanız, olarak işaretlemelisiniz async Task
.
Hala beklemek istiyorsan, o zaman böyle sar await Task.Run(() => blah())
await Task.Run(() => An_async_void_method_I_can_not_modify_now())
await Task.Run(() => blah())
yanıltıcıdır. Bu, zaman uyumsuzluk işlevinin tamamlanmasını beklemez blah
, sadece görevin (önemsiz) oluşturulmasını bekler ve blah()
tamamlanmadan hemen önce devam eder .
Thread.Sleep
eşzamansız değildir. Bu soru bir async void
işlevi beklemekle ilgili , diyelimasync void blah() { Task.Delay(10000); }
En iyi çözüm kullanmaktır async Task
. Bir kaçınılmazlığı async void
olan çeşitli nedenlerden kaçınmalısınız .
Yöntem ise olamaz dönmek için yapılacak Task
(örneğin, bir olay işleyicisi var), o zaman kullanabilirsiniz SemaphoreSlim
o çıkmak üzereyken yöntem sinyali olması. Bunu bir finally
blokta yapmayı düşünün .
bir AutoResetEvent yapın, işlevi çağırın, sonra AutoResetEvent'i bekleyin ve bittiğini bildiğinizde async void içinde ayarlayın.
Ayrıca, boş zaman uyumsuzluğunuzdan dönen bir Görevi de bekleyebilirsiniz
Manuel olarak herhangi bir şey yapmanıza gerek yoktur, await
anahtar kelime blah()
geri dönene kadar işlev yürütmeyi duraklatır .
private async void SomeFunction()
{
var x = await LoadBlahBlah(); <- Function is not paused
//rest of the code get's executed even if LoadBlahBlah() is still executing
}
private async Task<T> LoadBlahBlah()
{
await DoStuff(); <- function is paused
await DoMoreStuff();
}
T
nesne blah()
döndürme türüdür
Gerçekten await
bir void
işlev LoadBlahBlah()
yapamazsın, bu yüzden olamazvoid
LoadBlahBlah()
Bitirmek için beklemek istiyorum , değilblah()
Bunun eski bir soru olduğunu biliyorum, ama bu hala yürümeye devam ettiğim bir sorun ve yine de async / await'i bir async geçersiz imza yönteminde kullanırken bunu doğru bir şekilde yapmak için hala net bir çözüm yok.
Ancak, .Wait () void yöntemi içinde düzgün çalıştığını fark ettim.
ve eşzamansız boşluk ve boşluk aynı imzayı taşıdığından, aşağıdakileri yapmanız gerekebilir.
void LoadBlahBlah()
{
blah().Wait(); //this blocks
}
Kafa karıştırıcı bir şekilde yeterli zaman uyumsuzluğu / beklemesi bir sonraki kodu engellemez.
async void LoadBlahBlah()
{
await blah(); //this does not block
}
Kodunuzu koda dönüştürdüğünüzde, tahminim asenkron boşluğun dahili bir Görev (tıpkı zaman uyumsuz Görev gibi) oluşturmasıdır, ancak imza bu dahili Görevleri döndürmeyi desteklemediğinden
bu, dahili olarak asenkron boşluk yönteminin dahili olarak asenkron yöntemleri hala "bekleyebileceği" anlamına gelir. ancak harici olarak dahili görevin ne zaman tamamlandığını bilemez.
Sonuç olarak, asenkron boşluğun amaçlandığı gibi çalıştığı ve dahili Görev'den geri bildirime ihtiyacınız varsa, bunun yerine asenkron Görev imzasını kullanmanız gerekir.
Umarım başıboşum da cevap arayan herkese mantıklı geliyor.
Düzenleme: Bazı örnek kodlar yaptım ve aslında neler olduğunu görmek için koda.
static async void Test()
{
await Task.Delay(5000);
}
static async Task TestAsync()
{
await Task.Delay(5000);
}
Dönüşür (değiştir: Vücut kodunun burada değil, statemachines'de olduğunu biliyorum, ancak statemachines temelde aynıydı, bu yüzden onları eklemeye zahmet etmedim)
private static void Test()
{
<Test>d__1 stateMachine = new <Test>d__1();
stateMachine.<>t__builder = AsyncVoidMethodBuilder.Create();
stateMachine.<>1__state = -1;
AsyncVoidMethodBuilder <>t__builder = stateMachine.<>t__builder;
<>t__builder.Start(ref stateMachine);
}
private static Task TestAsync()
{
<TestAsync>d__2 stateMachine = new <TestAsync>d__2();
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>1__state = -1;
AsyncTaskMethodBuilder <>t__builder = stateMachine.<>t__builder;
<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
AsyncVoidMethodBuilder veya AsyncTaskMethodBuilder aslında Start yönteminde engellenecekleri ima edecek ve başlatıldıktan sonra her zaman eşzamansız olarak çalışacak herhangi bir koda sahip değildir.
yani geri dönen Görev olmadan, tamamlanıp tamamlanmadığını kontrol etmenin bir yolu olmazdı.
beklendiği gibi, yalnızca zaman uyumsuz çalışan Görev'i başlatır ve sonra kodda devam eder. ve zaman uyumsuz Görev, önce Görev'i başlatır ve sonra geri döndürür.
bu yüzden cevabım hiçbir zaman async void'i kullanmak değildir, görevin ne zaman yapıldığını bilmeniz gerekiyorsa, async Task'ın amacı budur.