async/awaitによるマルチスレッド処理
返り値のないメソッドの場合
private async void btnStart_Click(object sender, EventArgs e) { Console.WriteLine("Start:" + DateTime.Now.ToString("HH:mm:ss.ff")); await Count(); Console.WriteLine("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff")); } private async Task Count() { int intValue = 1; await Task.Run(() => { for(int intCount = 0; intCount < 15; intCount++) { intValue *= 2; Console.WriteLine(intValue); System.Threading.Thread.Sleep(100); } }); }
別スレッドからキャンセル処理を行う場合は下記のようになる。
// トークン private CancellationTokenSource objToken = null; private async void btnStart_Click(object sender, EventArgs e) { Console.WriteLine("Start:" + DateTime.Now.ToString("HH:mm:ss.ff")); await Count(); Console.WriteLine("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff")); } private async Task Count() { int intValue = 1; objToken = new CancellationTokenSource(); await Task.Run(() => { for(int intCount = 0; intCount < 15; intCount++) { // キャンセルフラグが立っていたら処理を抜ける if(objToken.IsCancellationRequested == true) { return; } intValue *= 2; Console.WriteLine(intValue); System.Threading.Thread.Sleep(100); } }, objToken.Token); } /// <summary> /// キャンセル処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnCancel_Click(object sender, EventArgs e) { if(objToken != null) { objToken.Cancel(); } }
また、IsCancellationRequested ではなく ThrowIfCancellationRequested を用いることで、
例外として処理することもできる。
// トークン private CancellationTokenSource objToken = null; private async void btnStart_Click(object sender, EventArgs e) { Console.WriteLine("Start:" + DateTime.Now.ToString("HH:mm:ss.ff")); try { await Count(); Console.WriteLine("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff")); } catch (OperationCanceledException exCanceled) { // キャンセル時 Console.WriteLine("Canceled:" + DateTime.Now.ToString("HH:mm:ss.ff")); } } private async Task Count() { try { int intValue = 1; objToken = new CancellationTokenSource(); await Task.Run(() => { try { for (int intCount = 0; intCount < 15; intCount++) { // キャンセルフラグが立っていたらOperationCanceledExceptionを発生させる objToken.Token.ThrowIfCancellationRequested(); intValue *= 2; Console.WriteLine(intValue); System.Threading.Thread.Sleep(100); } } catch (OperationCanceledException exCanceled) { // キャンセル時 throw (exCanceled); } }, objToken.Token); } catch (Exception ex) { throw (ex); } } /// <summary> /// キャンセル処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnCancel_Click(object sender, EventArgs e) { if (objToken != null) { objToken.Cancel(); } }
返り値のあるメソッドの場合
private async void btnStart_Click(object sender, EventArgs e) { Console.WriteLine("Start:" + DateTime.Now.ToString("HH:mm:ss.ff")); int intResult = await Count(); Console.WriteLine("Total:" + intResult); Console.WriteLine("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff")); } private async Task<int> Count() { int intValue = 1; int intResult = await Task.Run(() => { int intSum = 0; for(int intCount = 0; intCount < 15; intCount++) { intValue *= 2; Console.WriteLine(intValue); intSum += intValue; System.Threading.Thread.Sleep(100); } return intSum; }); return intResult; }
また、VB.NETの場合は下記のようになる(返り値のないメソッド)
Private Async Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click Debug.Print("Start:" + DateTime.Now.ToString("HH:mm:ss.ff")) Await Count() Debug.Print("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff")) End Sub Private Async Function Count() As Task Dim intValue As Integer = 1 Await Task.Run(Sub() For intCount = 0 To 14 intValue *= 2 Debug.Print(intValue) System.Threading.Thread.Sleep(100) Next End Sub) End Function
ディスカッション
コメント一覧
まだ、コメントがありません