Async / wait - kada man reikia grąžinti tuščią tuščią užduotį?

Kokius scenarijus norite naudoti

 public async Task AsyncMethod(int num) 

vietoj

 public async void AsyncMethod(int num) 

Vienintelis scenarijus, kurį galiu galvoti, yra tai, kad jums reikia užduoties sekti jos pažangą.

Be to, šis metodas nėra raktinių žodžių asinchronizavimas ir lūkesčiai?

 public static async void AsyncMethod2(int num) { await Task.Factory.StartNew(() => Thread.Sleep(num)); } 
349
27 авг. nustatė user981225 Rugpjūtis 27 2012-08-27 17:33 '12, 17:33, 2012-08-27 17:33
@ 6 atsakymai

1) Paprastai norite grąžinti Task . Pagrindinė išimtis turėtų būti, kai jums reikia void grąžos tipo (įvykiams). Jei nėra pagrindo atsisakyti await jūsų užduoties, kodėl jis turėtų būti išjungtas?

2) asinchroniniai metodai, kurie grąžina void yra ypatingi kitame aspekte: jie yra asinchroniniai aukščiausio lygio operacijos ir turi papildomų taisyklių, kurios pasirodo, kai jūsų užduotis grąžina išimtį. Paprasčiausias būdas yra parodyti skirtumą su pavyzdžiu:

 static async void f() { await h(); } static async Task g() { await h(); } static async Task h() { throw new NotImplementedException(); } private void button1_Click(object sender, EventArgs e) { f(); } private void button2_Click(object sender, EventArgs e) { g(); } private void button3_Click(object sender, EventArgs e) { GC.Collect(); } 

f išimtis visada yra „stebima“. Išimtis, kuri palieka asinchroninį aukščiausio lygio metodą, paprasčiausiai traktuojama kaip bet kuri kita neišlaikyta išimtis. g išimtis niekada nevyksta. Kai šiukšlių surinkėjas ateina išvalyti užduotį, jis mato, kad uždavinys sukėlė išimtį, ir niekas išimties nepadarė. Kai taip nutinka, vykdomas TaskScheduler.UnobservedTaskException tvarkytojas. Jūs niekada neturėtumėte leisti tai įvykti. Jei norite naudoti savo pavyzdį,

 public static async void AsyncMethod2(int num) { await Task.Factory.StartNew(() => Thread.Sleep(num)); } 

Taip, naudokite async ir await čia, jie įsitikins, kad jūsų metodas vis dar veikia tinkamai, jei išimtis išimta.

Norėdami gauti daugiau informacijos, žr. Http://msdn.microsoft.com/en-us/magazine/jj991977.aspx

318
27 авг. atsakymą pateikė user743382 27 rug . 2012-08-27 17:53 '12, 17:53, 2012-08-27 17:53

Su šiuo labai naudingu straipsniu apie async ir void , aš parašiau Jerome Laban: http://www.jaylee.org/post/2012/07/08/c-sharp-async-tips-and-tricks-part-2- async-void.aspx

Esmė yra ta, kad async+void gali sugadinti sistemą ir paprastai naudoti tik trečiosios šalies įvykių tvarkytojams.

border=0

To priežastis yra sinchronizavimo kontekstas, kurį naudoja „AsyncVoidMethodBuilder“, o tai nėra šiame pavyzdyje. Kai nėra supančio sinchronizavimo konteksto, bet kokia išimtis, kuri nėra tvarkoma aync void metodo kūno, yra grąžinta „ThreadPool“. Nors atrodo, kad nėra jokios kitos loginės vietos, kur tokia nepanaudota išimtis gali būti išmesta, gaila, kad procesas sustoja, nes nepanaudotos ThreadPool išimtys efektyviai užbaigia procesą su .NET 2.0. Naudodami „AppDomain.UnhandledException“ įvykį, galite sugauti visas nepanaudotas išimtis, tačiau nėra galimybės atgauti šio įvykio.

Rašydami UI įvykių tvarkytojus, asinchroninio tuščio metodai yra kažkaip neskausmingi, nes išimtys tvarkomos taip pat, kaip ir ne asinchroniniuose metoduose; jie yra išmesti į dispečerį. Daugeliu atvejų yra galimybė susigrąžinti iš tokių išimčių. Vis dėlto ne vartotojo sąsajos įvykių tvarkytojai, o asinchroniniai negaliojantys metodai yra kažkaip pavojingi naudoti ir gali būti ne taip lengvai rasti.

28
11 апр. Atsakymą davė Davide Icardi, balandžio 11 d. 2014-04-11 18:40 '14 at 18:40 2014-04-11 18:40

Aš gavau aiškią idėją iš šių pareiškimų.

  • Asinchroniniai tuštumo metodai turi skirtingą klaidų tvarkymo semantiką. Kai išimtis yra išmesta iš async užduoties arba asinchronizavimo užduoties, ši išimtis yra užfiksuota ir padėta į užduočių objektą. Naudojant async void metodus, nėra užduoties objekto, todėl bet kokios išimtys, kurios nėra įtrauktos į async void metodą, bus pridėtos tiesiai į SynchronizationContext (SynchronizationContext yra vieta, kur "gali būti įvykdytas kodas"), kuris buvo aktyvus, kai prasidėjo asinchroninio tuščio metodas

„Cant“ bus sugautas su asinchroninio negaliojimo metodo išimtimis

 private async void ThrowExceptionAsync() { throw new InvalidOperationException(); } public void AsyncVoidExceptions_CannotBeCaughtByCatch() { try { ThrowExceptionAsync(); } catch (Exception) { // The exception is never caught here! throw; } } 

Šios išimtys gali būti stebimos naudojant „AppDomain.UnhandledException“ arba panašų „GUI / ASP.NET“ programos įvykį, tačiau šių įvykių naudojimas reguliariajam išimties tvarkymui yra nepalaikomo receptas (dėl to programa netinkama).

  1. Asinchroniniai metodai turi skirtingą semantiką. Asinchroniniai metodai, kurie grąžina užduotį arba užduotį, gali būti lengvai surinkti naudojant laukimą, užduotį. Asinchroniniai metodai, kurie grąžina negaliojančius, nesuteikia paprasto būdo pranešti apie užbaigtą skambinimo kodą. Lengva pradėti keletą asinchroninių metodų, tačiau nėra lengva nustatyti, kada jie baigti. „Async void“ metodai praneša „SynchronizationContext“, kai jie pradės ir baigsis, tačiau pritaikoma „SynchronizationContext“ yra sudėtingas sprendimas įprastam programos kodui.

  2. „Async Void“ metodas yra naudingas, kai naudojamas sinchroninis įvykių tvarkytojas, nes jie generuoja išimtis tiesiogiai „SynchronizationContext“, kuris yra panašus į tai, kaip veikia sinchroniniai įvykių tvarkytojai.

Sužinokite daugiau apie šią nuorodą https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

15
25 мая '17 в 11:39 2017-05-25 11:39 atsakymas pateikiamas Nayas Subramanian gegužės 25 d. 17, 11:39

Manau, kad galite naudoti async void paleisti fonines operacijas, kai esate atsargūs. Mintys?

 class Program { static bool isFinished = false; static void Main(string[] args) { // Kick off the background operation and don't care about when it completes BackgroundWork(); Console.WriteLine("Press enter when you're ready to stop the background operation."); Console.ReadLine(); isFinished = true; } // Using async void to kickoff a background operation that nobody wants to be notified about when it completes. static async void BackgroundWork() { // It important to catch exceptions so we don't crash the appliation. try { // This operation will end after ten interations or when the app closes. Whichever happens first. for (var count = 1; count <= 10  !isFinished; count++) { await Task.Delay(1000); Console.WriteLine($"{count} seconds of work elapsed."); } Console.WriteLine("Background operation came to an end."); } catch (Exception x) { Console.WriteLine("Caught exception:"); Console.WriteLine(x.ToString()); } } } 
3
16 февр. Atsakymas duotas bboyle1234 16 vasaris 2018-02-16 15:43 '18 prie 15:43 2018-02-16 15:43

Problema, kai skambinate async negaliojančia, yra tai, kad net neatsiunčiate užduoties, neturite galimybės išsiaiškinti, kada baigta funkcijų užduotis (žr. „ Https://blogs.msdn.microsoft.com/oldnewthing/20170720-00/?p = 96655 )

Štai trys būdai, kaip skambinti async funkcijai:

 async Task<T> SomethingAsync() { ... return t; } async Task SomethingAsync() { ... } async void SomethingAsync() { ... } 

Visais atvejais funkcija paverčiama užduočių grandine. Skirtumas yra tas, kad funkcija grįžta.

Pirmuoju atveju funkcija grąžina užduotį, kuri galiausiai lemia t.

Antruoju atveju funkcija grąžina užduotį, kurioje nėra produkto, bet vis tiek galite ją atpažinti, kai jis baigiasi.

Trečiasis atvejis yra nemalonus. Trečiasis atvejis yra panašus į antrąjį atvejį, išskyrus tai, kad net neatsiunčiate užduoties. Jūs nežinote, kada baigsis funkcija.

Asinchroninis atvejis yra „ugnis ir pamiršti“: paleisite užduočių grandinę, bet nesirūpinate, kai jis baigtas. Kai funkcija sugrįžta, viskas, ką žinote, yra visa, kas įvykdyta iki pirmojo laukimo. Viskas po pirmojo laukimo bus pradėta tam tikru neapibrėžtu klausimu ateityje, kuriai jūs neturite prieigos.

2
19 июня '18 в 18:31 2018-06-19 18:31 atsakymą pateikė vartotojo8128167 birželio 19 d. 18 val. 18:31 2018-06-19 18:31

Mano atsakymas yra paprastas, jūs patranka laukite tuščio metodo Klaida CS4008 Negalima laukti, kol bus „void“ TestAsync e: testasAsync TestAsync

Todėl, jei metodas yra asinchroninis, geriau tikėtis, nes jūs galite prarasti async pranašumą.

0
20 сент. atsakymas duotas Serg Sh 20 sen. 2018-09-20 19:21 '18, 07:21 pm 2018-09-20 19:21

Kiti klausimai apie žymenis arba Užduoti klausimą