C #: рдХрд┐рд╕реА рднреА рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛

рдирдорд╕реНрдХрд╛рд░, рд╣реЗрдмреНрд░! рд╣рдо C # рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦрддреЗ рд╣реИрдВред рдЖрдЬ рд╣рдо рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рдврд╛рдВрдЪреЗ рдореЗрдВ рдХрд┐рд╕реА рднреА рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рдПрдХрд▓ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдпрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛-рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкрд░рд┐рджреГрд╢реНрдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗред рд╣рдо рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди, рдбреЗрдбрд▓реЙрдХ, рдСрдкрд░реЗрдЯрд░ рд╕реЗрдЯрд┐рдВрдЧреНрд╕, рдЕрдкрд╡рд╛рдж рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдФрд░ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╡рд┐рд╖рдпреЛрдВ рдкрд░ рд╕реНрдкрд░реНрд╢ рдХрд░реЗрдВрдЧреЗред рдЕрдм рд╕рдореНрдорд┐рд▓рд┐рдд рд╣реЛрдВ!



рдкрд┐рдЫрд▓реЗ рд╕рдВрдмрдВрдзрд┐рдд рд▓реЗрдЦ


C # рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рддрд░реАрдХреЛрдВ рдХреЗ рд▓рдЧрднрдЧ рдХрд┐рд╕реА рднреА рдЧреИрд░-рдорд╛рдирдХ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрд░рд┐рджреГрд╢реНрдп рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╕рдордЭрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ: рдореМрдЬреВрджрд╛ рд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХреЛрдб рдХреЛ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдирд╛ рдпрдерд╛рд╕рдВрднрд╡ рд╕рд░рд▓ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЖрдк рд╡рд╛рдкрд╕реА рдЯрд╛рдЗрдк рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ async рдХреАрд╡рд░реНрдб рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЗ рдирд╛рдо рдХреЗ рд▓рд┐рдП Async рдкреНрд░рддреНрдпрдп рдЬреЛрдбрд╝реЗрдВ, рдФрд░ рдкреВрд░реА рддрд░рд╣ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд╡рд┐рдзрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣рд╛рдБ рдФрд░ рдЯреЗрдХреНрд╕реНрдЯ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХреАрд╡рд░реНрдб рдЬреЛрдбрд╝реЗрдВред



рдПрдХ "рд╕рд░рд▓" рдкрд░рд┐рджреГрд╢реНрдп рдирд╛рдЯрдХреАрдп рд░реВрдк рд╕реЗ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рддрд░реАрдХреЛрдВ рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЗ рдХрдИ рдкрд╣рд▓реБрдУрдВ рдХреЛ рдмрджрд▓рддрд╛ рд╣реИ: рдПрдХ рдХрд╛рд░реНрдп рдХреА рдЕрд╡рдзрд┐ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛рдиреЗ рд╕реЗ рд▓реЗрдХрд░ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рддрдХред рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдареЛрд╕ рдФрд░ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд▓рдЧ рд░рд╣реА рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ, рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рддрд░реАрдХреЛрдВ рдХреА рд╕рд░рд▓рддрд╛ рдмрд╣реБрдд рднреНрд░рд╛рдордХ рд╣реЛ рдЬрд╛рддреА рд╣реИред

рд╕рд┐рдВрдХ рд╕рдВрджрд░реНрдн


рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ (UI) рд╡рд┐рдХрд╛рд╕ рдПрдХ рдРрд╕рд╛ рдХреНрд╖реЗрддреНрд░ рд╣реИ рдЬрд╣рд╛рдБ рдЙрдкрд░реЛрдХреНрдд рдкрд░рд┐рджреГрд╢реНрдп рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдереНрд░реЗрдб рдореЗрдВ рд▓рдВрдмреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдХрд╛рд░рдг, рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕рдордп рдмрдврд╝ рдЬрд╛рддреА рд╣реИ, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЛ рд╣рдореЗрд╢рд╛ рдПрдХ рдмрд╣реБрдд рдкреНрд░рднрд╛рд╡реА рдЙрдкрдХрд░рдг рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред

private async void buttonOk_ClickAsync(object sender, EventArgs args) { textBox.Text = "Running.."; // 1 -- UI Thread var result = await _stockPrices.GetStockPricesForAsync("MSFT"); // 2 -- Usually non-UI Thread textBox.Text = "Result is: " + result; //3 -- Should be UI Thread } 

рдХреЛрдб рдмрд╣реБрдд рд╕рд░рд▓ рджрд┐рдЦрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИред рдЕрдзрд┐рдХрд╛рдВрд╢ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдмрдВрдз рд╣реИрдВ: рдпреВрдЖрдИ рддрддреНрд╡реЛрдВ рдХреЛ рдХреЗрд╡рд▓ рд╡рд┐рд╢реЗрд╖ рдереНрд░реЗрдбреНрд╕ рджреНрд╡рд╛рд░рд╛ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрджрд┐ рдкрдВрдХреНрддрд┐ 3 рдореЗрдВ рдереНрд░реЗрдб рдкреВрд▓ рд╕реЗ рдереНрд░реЗрдб рдореЗрдВ рдХрд╛рд░реНрдп рдХреА рдЕрд╡рдзрд┐ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╣реИ, рддреЛ рдкрдВрдХреНрддрд┐ 3 рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рдЬрд╛рдиреА рдЬрд╛рддреА рд╣реИ, рдФрд░ .NET рдлреНрд░реЗрдорд╡рд░реНрдХ 2.0 рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдПрдХ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рд╕рдВрджрд░реНрдн рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рджрд┐рдЦрд╛рдИ рджреА рд╣реИред

рдкреНрд░рддреНрдпреЗрдХ UI рдПрдХ рдпрд╛ рдЕрдзрд┐рдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдереНрд░реЗрдбреНрд╕ рдореЗрдВ рдорд╛рд░реНрд╢рд▓рд┐рдВрдЧ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рдЙрдкрдпреЛрдЧрд┐рддрд╛рдУрдВ рдХреЛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред Windows рдкреНрд░рдкрддреНрд░ Control.Invoke рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред Control.Invoke рд╡рд┐рдзрд┐, WPF Dispatcher.Invoke рд╡рд┐рдзрд┐ Control.Invoke , рдЕрдиреНрдп рд╕рд┐рд╕реНрдЯрдо рдЕрдиреНрдп рд╡рд┐рдзрд┐рдпреЛрдВ рддрдХ рдкрд╣реБрдБрдЪ рд╕рдХрддреЗ рд╣реИрдВред рдЗрди рд╕рднреА рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рдпреЛрдЬрдирд╛рдПрдВ рдХрд╛рдлреА рд╣рдж рддрдХ рд╕рдорд╛рди рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рднрд┐рдиреНрди рд╣реИрдВред рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рд╕рдВрджрд░реНрдн рдЖрдкрдХреЛ "рд╡рд┐рд╢реЗрд╖" рд╕рдВрджрд░реНрдн рдореЗрдВ рдХреЛрдб рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдкреАрдЖрдИ рдкреНрд░рджрд╛рди рдХрд░рдХреЗ рдорддрднреЗрджреЛрдВ рд╕реЗ рдЕрдореВрд░реНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬреЛ рдХрд┐ рдЗрд╕ рддрд░рд╣ рдХреЗ рд╡реНрдпреБрддреНрдкрдиреНрди рдкреНрд░рдХрд╛рд░реЛрдВ рдЬреИрд╕реЗ рдХрд┐ WindowsFormsSynchronizationContext , DispatcherSynchronizationContext , рдЖрджрд┐ рджреНрд╡рд╛рд░рд╛ рдорд╛рдореВрд▓реА рд╡рд┐рд╡рд░рдг рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред

рдзрд╛рдЧреЗ рдХреА рдЖрддреНрдореАрдпрддрд╛ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕реА # рдкреНрд░реЛрдЧреНрд░рд╛рдорд░реНрд╕ рдиреЗ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЪрд░рдг рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рд╕рдВрджрд░реНрдн рдХреЛ рдкреЗрд╢ рдХрд░рдиреЗ рдФрд░ рдЗрд╕ рд╕рдВрджрд░реНрдн рдореЗрдВ рд╕рднреА рдмрд╛рдж рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред рдЕрдм, рдкреНрд░рддреАрдХреНрд╖рд┐рдд рдХрдердиреЛрдВ рдХреЗ рдмреАрдЪ рдкреНрд░рддреНрдпреЗрдХ рдмреНрд▓реЙрдХ рдХреЛ рдпреВрдЬрд░ рдЗрдВрдЯрд░рдлреЗрд╕ рдереНрд░реЗрдб рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдореБрдЦреНрдп рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╕рдВрднрд╡ рдмрдирд╛рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрд╕ рд╕рдорд╛рдзрд╛рди рдиреЗ рдХрдИ рдирдИ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рдЬрдиреНрдо рджрд┐рдпрд╛ред

рдЧрддрд┐рд░реЛрдз


рдЖрдЗрдП рдХреЛрдб рдХрд╛ рдПрдХ рдЫреЛрдЯрд╛, рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рд╕рд░рд▓ рдЯреБрдХрдбрд╝рд╛ рджреЗрдЦреЗрдВред рдХреНрдпрд╛ рдпрд╣рд╛рдВ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рд╣реИ?

 // UI code private void buttonOk_Click(object sender, EventArgs args) { textBox.Text = "Running.."; var result = _stockPrices.GetStockPricesForAsync("MSFT").Result; textBox.Text = "Result is: " + result; } // StockPrices.dll public Task<decimal> GetStockPricesForAsync(string symbol) { await Task.Yield(); return 42; } 

рдпрд╣ рдХреЛрдб рдЧрддрд┐рд░реЛрдз рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдереНрд░реЗрдб рдПрдХ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдСрдкрд░реЗрд╢рди рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХреЗ рд▓рд┐рдП рд╕рдордХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╡рд┐рдзрд┐ рдХреЛ рдкреВрд░рд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ GetStockPricesForAsync рдХреА рджреВрд╕рд░реА рдкрдВрдХреНрддрд┐ рдХреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдереНрд░реЗрдб рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдЧрддрд┐рд░реЛрдз рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред

рдЖрдкрдХреЛ рдЖрдкрддреНрддрд┐ рд╣реЛрдЧреА рдХрд┐ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╣рд▓ рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдлреА рдЖрд╕рд╛рди рд╣реИред рд╣рд╛рдБ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛрдб рд╕реЗ Task.Result рдпрд╛ Task.Wait рд▓рд┐рдП рд╕рднреА рдХреЙрд▓реЛрдВ рдХреЛ рдкреНрд░рддрд┐рдмрдВрдзрд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╕рдорд╕реНрдпрд╛ рддрдм рднреА рд╣реЛ рд╕рдХрддреА рд╣реИ рдпрджрд┐ рдЗрд╕ рддрд░рд╣ рдХреЗ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдШрдЯрдХ рдПрдХ рд╕рд╛рде рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдСрдкрд░реЗрд╢рди рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд░рд╣рд╛ рд╣реИ:

 // UI code private void buttonOk_Click(object sender, EventArgs args) { textBox.Text = "Running.."; var result = _stockPrices.GetStockPricesForAsync("MSFT").Result; textBox.Text = "Result is: " + result; } // StockPrices.dll public Task<decimal> GetStockPricesForAsync(string symbol) { // We know that the initialization step is very fast, // and completes synchronously in most cases, // let's wait for the result synchronously for "performance reasons". InitializeIfNeededAsync().Wait(); return Task.FromResult((decimal)42); } // StockPrices.dll private async Task InitializeIfNeededAsync() => await Task.Delay(1); 

рдпрд╣ рдХреЛрдб рдлрд┐рд░ рд╕реЗ рдЧрддрд┐рд░реЛрдз рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред рдЗрд╕реЗ рдХреИрд╕реЗ рд╣рд▓ рдХрд░реЗрдВ:

  • рдЖрдкрдХреЛ Task.Wait() рдпрд╛ Task.Result рдФрд░ рдХреЗ рд╕рд╛рде рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХреЛрдб рдХреЛ рдмреНрд▓реЙрдХ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП
  • рд▓рд╛рдпрдмреНрд░реЗрд░реА рдХреЛрдб рдореЗрдВ ConfigureAwait(false) рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред

рдкрд╣рд▓реА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХрд╛ рдЕрд░реНрде рд╕реНрдкрд╖реНрдЯ рд╣реИ, рдФрд░ рджреВрд╕рд░рд╛ рд╣рдо рдиреАрдЪреЗ рдмрддрд╛рдПрдВрдЧреЗред

рдкреНрд░рддреАрдХреНрд╖рд┐рдд рдХрдерди рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛


рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдПрдХ рдбреЗрдбрд▓реЙрдХ рдХреНрдпреЛрдВ рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рджреЛ рдХрд╛рд░рдг рд╣реИрдВ: Task.Wait() рдФрд░ InitializeIfNeededAsync рдореЗрдВ рдмрд╛рдж рдХреЗ рдЪрд░рдгреЛрдВ рдореЗрдВ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рд╕рдВрджрд░реНрдн рдХрд╛ рдЕрдкреНрд░рддреНрдпрдХреНрд╖ рдЙрдкрдпреЛрдЧред рдпрджреНрдпрдкрд┐ C # рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЙрд▓ рдХреЛ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рддрд░реАрдХреЛрдВ рд╕реЗ рдЕрд╡рд░реБрджреНрдз рдХрд░рдиреЗ рдХреА рдЕрдиреБрд╢рдВрд╕рд╛ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдпрд╣ рдЕрд╡рд░реБрджреНрдз рдЕрднреА рднреА рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред C # рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдПрдХ рдбреЗрдбрд▓реЙрдХ рд╕рдорд╕реНрдпрд╛ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдорд╛рдзрд╛рди рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ: Task.ConfigureAwait(continueOnCapturedContext:false) ред

рдЕрдЬреАрдм рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреЗ рдмрд╛рд╡рдЬреВрдж (рдпрджрд┐ рдПрдХ рд╡рд┐рдзрд┐ рдХреЙрд▓ рдХреЛ рдмрд┐рдирд╛ рдирд╛рдо рдХреЗ рддрд░реНрдХ рдХреЗ рдмрд┐рдирд╛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЗрд╕рдХрд╛ рдорддрд▓рдм рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реИ), рдпрд╣ рд╕рдорд╛рдзрд╛рди рдЕрдкрдирд╛ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ: рдпрд╣ рдПрдХ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рд╕рдВрджрд░реНрдн рдХреЗ рдмрд┐рдирд╛ рдирд┐рд╖реНрдкрд╛рджрди рдХреА рдордЬрдмреВрд░ рдирд┐рд░рдВрддрд░рддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред

 public Task<decimal> GetStockPricesForAsync(string symbol) { InitializeIfNeededAsync().Wait(); return Task.FromResult((decimal)42); } private async Task InitializeIfNeededAsync() => await Task.Delay(1).ConfigureAwait(false); 

рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдХрд╛рд░реНрдпред рдЬрд╛рд░реА Task.Delay(1 ) рдХрд╛рд░реНрдп (рдпрд╣рд╛рдВ рдЦрд╛рд▓реА рдХрдерди рд╣реИ) рдереНрд░реЗрдб рдкреВрд▓ рд╕реЗ рдереНрд░реЗрдб рдореЗрдВ рдпреЛрдЬрдирд╛ рдмрдирд╛рдИ рдЧрдИ рд╣реИ, рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдереНрд░реЗрдб рдореЗрдВ рдирд╣реАрдВ, рдЬреЛ рдЧрддрд┐рд░реЛрдз рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред

рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рд╕рдВрджрд░реНрдн рдХреЛ рдЕрдХреНрд╖рдо рдХрд░рдирд╛


рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ ConfigureAwait рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдкреИрджрд╛ рдХрд░рддрд╛ рд╣реИред рдпрд╣рд╛рдБ рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рдЙрджрд╛рд╣рд░рдг рд╣реИ:

 public Task<decimal> GetStockPricesForAsync(string symbol) { InitializeIfNeededAsync().Wait(); return Task.FromResult((decimal)42); } private async Task InitializeIfNeededAsync() { // Initialize the cache field first await _cache.InitializeAsync().ConfigureAwait(false); // Do some work await Task.Delay(1); } 

рдХреНрдпрд╛ рдЖрдк рд╕рдорд╕реНрдпрд╛ рджреЗрдЦрддреЗ рд╣реИрдВ? рд╣рдордиреЗ ConfigureAwait(false) рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛, рдЗрд╕рд▓рд┐рдП рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд▓реЗрдХрд┐рди рдПрдХ рддрдереНрдп рдирд╣реАрдВред

ConfigureAwait(false) рдПрдХ рдХрд╕реНрдЯрдо рд╡реЗрдЯрд░ ConfiguredTaskAwaitable рд╣реИрдЕрдЪреНрдЫреА рд╡рд╕реНрддреБ, рдФрд░ рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреЗрд╡рд▓ рддрднреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рдХрд╛рд░реНрдп рд╕рдордХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рдкреВрд░рд╛ рди рд╣реЛред рдпрд╣реА рд╣реИ, рдЕрдЧрд░ _cache.InitializeAsync() рд╕рдордХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдПрдХ рдЧрддрд┐рд░реЛрдз рдЕрднреА рднреА рд╕рдВрднрд╡ рд╣реИред

рдЧрддрд┐рд░реЛрдзреЛрдВ рдХреЛ рдЦрддреНрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, ConfigureAwait(false) рдкрджреНрдзрддрд┐ рдХреЗ рд▓рд┐рдП рдХреЙрд▓ рдХреЗ рд╕рд╛рде рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХрд╛ рдЗрдВрддрдЬрд╛рд░ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдХреЛ "рд╕рдЬрд╛рдпрд╛" рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рд╕рдм annoys рдФрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред

рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ, рдЖрдк рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╡рд┐рдзрд┐ рдореЗрдВ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рд╕рдВрджрд░реНрдн рдХреЛ рдЕрдХреНрд╖рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рднреА рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рддрд░реАрдХреЛрдВ рдореЗрдВ рд╡реЗрдЯрд░ рдХрд╕реНрдЯрдо рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

 private void buttonOk_Click(object sender, EventArgs args) { textBox.Text = "Running.."; var result = _stockPrices.GetStockPricesForAsync("MSFT").Result; textBox.Text = "Result is: " + result; } // StockPrices.dll public async Task<decimal> GetStockPricesForAsync(string symbol) { // The rest of the method is guarantee won't have a current sync context. await Awaiters.DetachCurrentSyncContext(); // We can wait synchronously here and we won't have a deadlock. InitializeIfNeededAsync().Wait(); return 42; } 

Awaiters.DetachCurrentSyncContext рдирд┐рдореНрди рдХрд╕реНрдЯрдо рд╡реЗрдЯрд░ рдСрдмреНрдЬреЗрдХреНрдЯ рд▓реМрдЯрд╛рддрд╛ рд╣реИ:

 public struct DetachSynchronizationContextAwaiter : ICriticalNotifyCompletion { /// <summary> /// Returns true if a current synchronization context is null. /// It means that the continuation is called only when a current context /// is presented. /// </summary> public bool IsCompleted => SynchronizationContext.Current == null; public void OnCompleted(Action continuation) { ThreadPool.QueueUserWorkItem(state => continuation()); } public void UnsafeOnCompleted(Action continuation) { ThreadPool.UnsafeQueueUserWorkItem(state => continuation(), null); } public void GetResult() { } public DetachSynchronizationContextAwaiter GetAwaiter() => this; } public static class Awaiters { public static DetachSynchronizationContextAwaiter DetachCurrentSyncContext() { return new DetachSynchronizationContextAwaiter(); } } 

DetachSynchronizationContextAwaiter рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд░рддрд╛ рд╣реИ: Async рд╡рд┐рдзрд┐ рдПрдХ рдЧреИрд░-рд╢реВрдиреНрдп рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рд╕рдВрджрд░реНрдн рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреА рд╣реИред рд▓реЗрдХрд┐рди рдЕрдЧрд░ IsCompleted рд╡рд┐рдзрд┐ рдмрд┐рдирд╛ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдХрд╛рдо рдХрд░рддреА рд╣реИ, рддреЛ IsCompleted property рд╕рд╣реА рд╣реЛ рдЬрд╛рддреА рд╣реИ, рдФрд░ рд╡рд┐рдзрд┐ рдХреА рдирд┐рд░рдВрддрд░рддрд╛ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝ рдХреА рдЬрд╛рддреА рд╣реИред

рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдкрджреНрдзрддрд┐ рдереНрд░реЗрдб рдкреВрд▓ рдореЗрдВ рдПрдХ рдереНрд░реЗрдб рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдиреЗ рдкрд░ рд╕реЗрд╡рд╛ рдбреЗрдЯрд╛ рд╢реВрдиреНрдп рдХреЗ рдХрд░реАрдм рд╣реИ, рдФрд░ рдереНрд░реЗрдб рдкреВрд▓ рд╕реЗ рдереНрд░реЗрдб рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдереНрд░реЗрдб рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрди рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╛рд░ рднреБрдЧрддрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рдЕрдиреНрдп рд▓рд╛рдн рдиреАрдЪреЗ рд╕реВрдЪреАрдмрджреНрдз рд╣реИрдВред

  • рддреНрд░реБрдЯрд┐ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдХрдо рд╣реЛ рдЬрд╛рддреА рд╣реИред ConfigureAwait(false) рдХреЗрд╡рд▓ рддрднреА рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬрдм рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХрд╛ рдЗрдВрддрдЬрд╛рд░ рд╣реИред рдпрд╣ рдХрдо рд╕реЗ рдХрдо рдПрдХ рдЪреАрдЬ рдХреЛ рднреВрд▓рдиреЗ рдХреЗ рд▓рд╛рдпрдХ рд╣реИ - рдФрд░ рдПрдХ рдЧрддрд┐рд░реЛрдз рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдХрд╕реНрдЯрдо рд╡реЗрдЯрд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рд╕рднреА рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ Awaiters.DetachCurrentSyncContext() рд╢реБрд░реВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдпрд╣рд╛рдВ рд╕рдВрднрд╡ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрдирдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдмрд╣реБрдд рдХрдо рд╣реИред
  • рдкрд░рд┐рдгрд╛рдореА рдХреЛрдб рдЕрдзрд┐рдХ рдШреЛрд╖рдгрд╛рддреНрдордХ рдФрд░ рд╕реНрдкрд╖реНрдЯ рд╣реИред рдХрдИ рдХреЙрд▓ рдХреЗ рд╕рд╛рде ConfigureAwait рд╡рд┐рдзрд┐ рдореЗрд░реЗ рд▓рд┐рдП рдХрдо рдкрдардиреАрдп рд▓рдЧрддреА рд╣реИ (рдЕрддрд┐рд░рд┐рдХреНрдд рддрддреНрд╡реЛрдВ рдХреЗ рдХрд╛рд░рдг) рдФрд░ рд╢реБрд░реБрдЖрддреА рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдЬрд╛рдирдХрд╛рд░реАрдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИред

рдЕрдкрд╡рд╛рдж рд╕рдВрднрд╛рд▓рдирд╛


рдЗрди рджреЛ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдореЗрдВ рдХреНрдпрд╛ рдЕрдВрддрд░ рд╣реИ:

рдЯрд╛рд╕реНрдХ mayFail = Task.FromException (рдирдпрд╛ ArgumentNullException ());

 // Case 1 try { await mayFail; } catch (ArgumentException e) { // Handle the error } // Case 2 try { mayFail.Wait(); } catch (ArgumentException e) { // Handle the error } 

рдкрд╣рд▓реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╕рдм рдХреБрдЫ рдЕрдкреЗрдХреНрд╖рд╛рдУрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░рддрд╛ рд╣реИ - рддреНрд░реБрдЯрд┐ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рджреВрд╕рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдРрд╕рд╛ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред TPL рд╕рдорд╛рдирд╛рдВрддрд░ рдХрд╛рд░реНрдп рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдФрд░ рд╕рдорд╛рдирд╛рдВрддрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдЯрд╛рд╕реНрдХ / рдЯрд╛рд╕реНрдХ рдХрдИ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ Task.Result рдФрд░ Task.Wait() рд╣рдореЗрд╢рд╛ рдПрдХ AggregateException рдлреЗрдВрдХ рджреЗрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рдХрдИ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реЛ рд╕рдХрддреА рд╣реИрдВред

рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╣рдорд╛рд░рд╛ рдореБрдЦреНрдп рдкрд░рд┐рджреГрд╢реНрдп рд╕рдм рдХреБрдЫ рдмрджрд▓ рджреЗрддрд╛ рд╣реИ: рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рддрд░реНрдХ рдХреЛ рдЫреВрдиреЗ рдХреЗ рдмрд┐рдирд╛ рдПрд╕рд┐рдВрдХреНрд╕ / рдкреНрд░рддреАрдХреНрд╖рд┐рдд рдСрдкрд░реЗрдЯрд░ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЕрд░реНрдерд╛рддреН, рдкреНрд░рддреАрдХреНрд╖рд┐рдд рдХрдерди Task.Result рд╕реЗ рднрд┐рдиреНрди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред Task.Result / Task.Wait() : рдпрд╣ Task.Wait() рдЕрдкрд╡рд╛рдж рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдПрдХ рдЕрдкрд╡рд╛рдж рдХреЗ рдЖрд╡рд░рдг рдХреЛ рд╣рдЯрд╛ рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЖрдЬ рд╣рдо рдкрд╣рд▓реЗ рдЕрдкрд╡рд╛рдж рдХрд╛ рдЪрдпрди рдХрд░реЗрдВрдЧреЗред

рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИ рдЕрдЧрд░ рдЯрд╛рд╕реНрдХ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╕рднреА рддрд░реАрдХреЗ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╣реИрдВ рдФрд░ рд╕рдорд╛рдирд╛рдВрддрд░ рдХрдореНрдкреНрдпреВрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рд╕рдм рдХреБрдЫ рдЕрд▓рдЧ рд╣реИ:

 try { Task<int> task1 = Task.FromException<int>(new ArgumentNullException()); Task<int> task2 = Task.FromException<int>(new InvalidOperationException()); // await will rethrow the first exception await Task.WhenAll(task1, task2); } catch (Exception e) { // ArgumentNullException. The second error is lost! Console.WriteLine(e.GetType()); } 

Task.WhenAll рджреЛ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдХрд╛рд░реНрдп рджреЗрддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдкреНрд░рддреАрдХреНрд╖рд┐рдд рд╡рд┐рд╡рд░рдг рдХреЗрд╡рд▓ рдкрд╣рд▓реЗ рдХреЛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдФрд░ рднрд░рддрд╛ рд╣реИред

рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рджреЛ рддрд░реАрдХреЗ рд╣реИрдВ:

  1. рдпрджрд┐ рдЙрдирдХреЗ рдкрд╛рд╕ рдПрдХреНрд╕реЗрд╕ рд╣реИ, рдпрд╛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдХрд╛рд░реНрдп рджреЗрдЦреЗрдВ
  2. рдХрд┐рд╕реА рдЕрдиреНрдп AggregateException рдореЗрдВ рд▓рд┐рдкрдЯреЗ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрд╡рд╛рдж рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП TPL рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВред

 try { Task<int> task1 = Task.FromException<int>(new ArgumentNullException()); Task<int> task2 = Task.FromException<int>(new InvalidOperationException()); // t.Result forces TPL to wrap the exception into AggregateException await Task.WhenAll(task1, task2).ContinueWith(t => t.Result); } catch(Exception e) { // AggregateException Console.WriteLine(e.GetType()); } 

Async рд╢реВрдиреНрдп рд╡рд┐рдзрд┐


рдЯрд╛рд╕реНрдХ-рдЖрдзрд╛рд░рд┐рдд рдкрджреНрдзрддрд┐ рдПрдХ рдЯреЛрдХрди рд▓реМрдЯрд╛рддреА рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрджрд┐ рдХрд╛рд░реНрдп рдЦреЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЯреЛрдХрди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдб рджреНрд╡рд╛рд░рд╛ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рджреБрд░реНрдЧрдо рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдПрдХ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдСрдкрд░реЗрд╢рди рдЬреЛ рд╢реВрдиреНрдп рд╡рд┐рдзрд┐ рдХреЛ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдб рдореЗрдВ рд╕рдВрднрд╛рд▓рд╛ рдирд╣реАрдВ рдЬрд╛ рд╕рдХрддрд╛ред рдЗрд╕ рдЕрд░реНрде рдореЗрдВ, рдЯреЛрдХрди рдмреЗрдХрд╛рд░ рдФрд░ рдЦрддрд░рдирд╛рдХ рд╣реИрдВ - рдЕрдм рд╣рдо рдЗрд╕реЗ рджреЗрдЦреЗрдВрдЧреЗред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╣рдорд╛рд░рд╛ рдореБрдЦреНрдп рдкрд░рд┐рджреГрд╢реНрдп рдЙрдирдХреЗ рдЕрдирд┐рд╡рд╛рд░реНрдп рдЙрдкрдпреЛрдЧ рдХреЛ рдорд╛рдирддрд╛ рд╣реИ:

 private async void buttonOk_ClickAsync(object sender, EventArgs args) { textBox.Text = "Running.."; var result = await _stockPrices.GetStockPricesForAsync("MSFT"); textBox.Text = "Result is: " + result; } 

рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ GetStockPricesForAsync рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХрддрд╛ рд╣реИ? рдПрдХ рдЕрдирд╣реЗрд▓реНрджреА рдХрд┐рдП рдЧрдП async void рд╡рд┐рдзрд┐ рдЕрдкрд╡рд╛рдж рдХреЛ рд╡рд░реНрддрдорд╛рди рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди рд╕рдиреНрджрд░реНрдн рдореЗрдВ рдорд╛рд░реНрд╢рд▓реНрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рд╕рдорд╛рди рдХреЛрдб рдХреЗ рд╕рдорд╛рди рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реИ (рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП AsyncMethodBuilder.cs рд╡реЗрдм рдкреЗрдЬ рдХрд╛ ThrowAsync рд╡рд┐рдзрд┐ рдЕрдиреБрднрд╛рдЧ рджреЗрдЦреЗрдВ)ред Windows рдкреНрд░рдкрддреНрд░реЛрдВ рдкрд░, рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдореЗрдВ рдПрдХ рдЕрдирд╣реЗрд▓реНрджреА рдЕрдкрд╡рд╛рдж Application.ThreadException рдЗрд╡реЗрдВрдЯ, WPF рдХреЗ рд▓рд┐рдП, Application.DispatcherUnhandledException рдЗрд╡реЗрдВрдЯ рдлрд╝рд╛рдпрд░ рдФрд░ рдЗрддрдиреЗ рдкрд░ рдЖрдЧ рд▓рдЧрд╛рддрд╛ рд╣реИред

рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд╢реВрдиреНрдп рд╡рд┐рдзрд┐ рдХреЛ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рд╕рдВрджрд░реНрдн рдирд╣реАрдВ рдорд┐рд▓рддрд╛ рд╣реИ? рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдПрдХ рдЕрдирд╣реЗрд▓реНрджреА рдЕрдкрд╡рд╛рдж рдПрдХ рдШрд╛рддрдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреНрд░реИрд╢ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред рдпрд╣ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ [ TaskScheduler.UnobservedTaskException ] рдЗрд╡реЗрдВрдЯ рдХреЛ рдлрд╛рдпрд░ рдирд╣реАрдВ рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рдпрд╣ AppDomain.UnhandledException TaskScheduler.UnobservedTaskException рдЗрд╡реЗрдВрдЯ рдореЗрдВ рдЖрдЧ рд▓рдЧрд╛ рджреЗрдЧрд╛ рдФрд░ рдлрд┐рд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдмрдВрдж рдХрд░ рджреЗрдЧрд╛ред рдпрд╣ рдЬрд╛рдирдмреВрдЭрдХрд░ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рдареАрдХ рд╡реИрд╕рд╛ рд╣реА рдкрд░рд┐рдгрд╛рдо рд╣реИ рдЬреИрд╕рд╛ рд╣рдореЗрдВ рдЪрд╛рд╣рд┐рдПред

рдЕрдм рдЖрдЗрдП рдПрдХ рдФрд░ рдкреНрд░рд╕рд┐рджреНрдз рддрд░реАрдХреЗ рд╕реЗ рджреЗрдЦреЗрдВ: рдХреЗрд╡рд▓ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдЗрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдХреЗ рд▓рд┐рдП рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╢реВрдиреНрдп рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ред

рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, asynch рд╢реВрдиреНрдп рд╡рд┐рдзрд┐ рджреБрд░реНрдШрдЯрдирд╛ рд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╕рд╛рди рд╣реИред

 public static Task<T> ActionWithRetry<T>(Func<Task<T>> provider, Action<Exception> onError) { // Calls 'provider' N times and calls 'onError' in case of an error. } public async Task<string> AccidentalAsyncVoid(string fileName) { return await ActionWithRetry( provider: () => { return File.ReadAllTextAsync(fileName); }, // Can you spot the issue? onError: async e => { await File.WriteAllTextAsync(errorLogFile, e.ToString()); }); } 

рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ, рд▓реИрдореНрдмреНрдбрд╛ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдпрд╣ рдХрд╣рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ рдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдЯрд╛рд╕реНрдХ-рдЖрдзрд╛рд░рд┐рдд рд╡рд┐рдзрд┐ рд╣реИ рдпрд╛ async рд╢реВрдиреНрдп рд╡рд┐рдзрд┐ рд╣реИ, рдФрд░ рдЗрд╕рд▓рд┐рдП рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЬрд╛рдБрдЪ рдХреЗ рдмрд╛рд╡рдЬреВрдж рдПрдХ рддреНрд░реБрдЯрд┐ рдЖрдкрдХреЗ рдХреЛрдб рдмреЗрд╕ рдореЗрдВ рд░реЗрдВрдЧ рд╕рдХрддреА рд╣реИред

рдирд┐рд╖реНрдХрд░реНрд╖


C # рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рдХрдИ рдкрд╣рд▓реВ рдПрдХрд▓ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрд░рд┐рджреГрд╢реНрдп рд╕реЗ рдкреНрд░рднрд╛рд╡рд┐рдд рдереЗ - рдмрд╕ рдореМрдЬреВрджрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЗ рд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХреЛрдб рдХреЛ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдирд╛:

  • рдкрд░рд┐рдгрд╛рдореА рддреБрд▓реНрдпрдХрд╛рд▓рди рд╕рдВрджрд░реНрдн рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдмрд╛рдж рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрди рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╣реИ, рдЬреЛ рдЧрддрд┐рд░реЛрдз рдХрд╛ рдХрд╛рд░рдг рдмрди рд╕рдХрддрд╛ рд╣реИред
  • рдЙрдиреНрд╣реЗрдВ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП, рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдХреЛрдб рдореЗрдВ рд╣рд░ рдЬрдЧрд╣ ConfigureAwait(false) рдХреЙрд▓ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред
  • рдХрд╛рд░реНрдп рдХрд╛ рдЗрдВрддрдЬрд╛рд░; рдкрд╣рд▓реА рддреНрд░реБрдЯрд┐ рдкреИрджрд╛ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рд╕рдорд╛рдирд╛рдВрддрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдЕрдкрд╡рд╛рдж рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЛ рдЬрдЯрд┐рд▓ рдмрдирд╛рддрд╛ рд╣реИред
  • рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдШрдЯрдирд╛рдУрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП Async рд╢реВрдиреНрдп рд╡рд┐рдзрд┐рдпрд╛рдБ рдкреНрд░рд╕реНрддреБрдд рдХреА рдЧрдИ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╡реЗ рджреБрд░реНрдШрдЯрдирд╛ рджреНрд╡рд╛рд░рд╛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИрдВ, рдЬреЛ рдХрд┐ рдПрдХ рдЕрдкрд╡рд╛рдж рдХреЛ рдлреЗрдВрдХрдиреЗ рдкрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдХреНрд░реИрд╢ рдХрд░ рджреЗрдЧрд╛ред

рдореБрдлреНрдд рдкрдиреАрд░ рдХреЗрд╡рд▓ рдПрдХ рдЪреВрд╣рд╛рджрд╛рди рдореЗрдВ рд╣реЛрддрд╛ рд╣реИред рдЙрдкрдпреЛрдЧ рдореЗрдВ рдЖрд╕рд╛рдиреА рдХрднреА-рдХрднреА рдЕрдиреНрдп рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рдмрдбрд╝реА рдХрдард┐рдирд╛рдЗрдпреЛрдВ рдХрд╛ рдХрд╛рд░рдг рдмрди рд╕рдХрддреА рд╣реИред рдпрджрд┐ рдЖрдк C # рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рдЗрддрд┐рд╣рд╛рд╕ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИрдВ, рддреЛ рдЕрдЬреАрдм рд╡реНрдпрд╡рд╣рд╛рд░ рдЕрдм рдЗрддрдирд╛ рдЕрдЬреАрдм рдирд╣реАрдВ рд▓рдЧрддрд╛ рд╣реИ, рдФрд░ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдХреЛрдб рдореЗрдВ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдХрд╛рдлреА рдХрдо рд╣реЛ рдЬрд╛рддреА рд╣реИред

Source: https://habr.com/ru/post/hi421245/


All Articles