Task③
async/await
await
メソッド内でTaskの実行を非同期的に待機する場合、awaitキーワードを付与します。
var task = Task.Run(() => hoge((); await task;
awaitした時点で、メソッドは待機状態となり、呼び出し元に処理が戻ります。
taskが完了するとメソッドが再開され、await以降の処理が行われます。
await以降に処理が存在しない場合、待機の必要がないため、awaitは不要です。
async
awaitキーワードを含むメソッドにはasyncキーワードを付与する必要があります。
private async {戻り値型} Hoge() { }
asyncなメソッドの戻り値型は以下のいずれかです。
Task
- メソッドが何らかの値をreturnしない場合
- 呼び出し元でtry/catchすることで例外処理可能
以下サンプルコードと実行結果です。
public static void Main(string[] args) { AsyncTest(); Console.WriteLine("AsyncTest Called"); Console.ReadKey(); } private static async Task AsyncTest() { try { await AsyncTask(); } catch (Exception e) { Console.WriteLine($"Message : {e.Message}"); } Console.WriteLine("AsyncTest Complete"); } private static async Task AsyncTask() { await Task.Delay(1000); Console.WriteLine("AsyncTask Complete"); throw new InvalidOperationException("Error in AsyncTask"); }
AsyncTest Called AsyncTask Complete Message : Error in AsyncTask AsyncTest Complete
Task<T>
- メソッドが何らかの値をreturnする場合
- Tはreturnする値の型
- 呼び出し元でtry/catchすることで例外処理可能
以下サンプルコードと実行結果です。 Main()の実装は同じです。
private static async Task AsyncTest() { try { var result = await AsyncHasValueTask(); Console.WriteLine(result); } catch (Exception e) { Console.WriteLine($"Message : {e.Message}"); } Console.WriteLine("AsyncTest Complete"); } private static async Task<string> AsyncHasValueTask() { await Task.Delay(1000); // このコメントアウトを解除すると、AsyncTest()で例外メッセージだけ出力されます。 //throw new InvalidOperationException("Error in AsyncHasValueTask"); return "AsyncHasValueTask Complete"; }
AsyncTest Called AsyncHasValueTask Complete AsyncTest Complete
void
- イベントハンドラーの場合
- 呼び出し元でawaitできず、例外も検出できないため、上記以外の使用は避ける
以下サンプルコードと実行結果です。 Main()の実装は同じです。 例外は処理されず、コンソールに出力されます。
private static async Task AsyncTest() { try { AsyncVoid(); // コンパイルエラーになるのでawaitできない } catch (Exception e) { Console.WriteLine($"Message : {e.Message}"); } Console.WriteLine("AsyncTest Complete"); } private static async void AsyncVoid() { await Task.Delay(1000); Console.WriteLine("AsyncVoid Complete"); throw new InvalidOperationException("Error in AsyncVoid"); }
AsyncTest Complete AsyncTest Called AsyncVoid Complete Unhandled Exception: System.InvalidOperationException: Error in AsyncVoid at ProgrammingInCSharp_Async.Program.AsyncVoid() in C:\Users\maki8\Documents\Visual Studio 2017\Projects\ProgrammingInCSharp_Async\ProgrammingInCSharp_Async\Program.cs:line 53 at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location where exception was thrown --- at System.Threading.ThreadPoolWorkQueue.Dispatch()