非同期処理のAsync/Awaitは便利です。
では、前ふりです。
GUIでの非同期処理って、いろいろと面倒なイメージがありませんか。
非同期処理を行う場合って、脳内ではこんなこと考えていませんでしたか?
ボタンを押す→処理が重たい→スレッドにする→最終結果を表示したいから、スレッド終了待ち→待ってるとGUI固まる→DoEventでごまかす。
結局、スレッドにする、しないにかかわらず、クリック後の処理で待ちたいけれど、固まったように見えないようにしなければ!ってことを考えていたのではないでしょうか。
まずは、今まで書いていたようなコードを見てみましょう。
private async void button1_Click( object sender, EventArgs e )
{
var msg = HeavyCalcurate_Thread();
MessageBox.Show( msg );
}
// 処理中でも、GUIを操作可能
private String HeavyCalcurate_Thread()
{
var task = new TaskFactory().StartNew( ()=>
{
for( var i = 0; i < 10; i++ )
{
System.Threading.Thread.Sleep( 2000 );
}
} );
// 終了待ち
var wait = false;
while( wait == false )
{
wait = task.Wait( 100 );
Application.DoEvents();//<---がんばって処理を逃がすw
}
return "完了";
}
要は、スレッドの処理待ちです。スレッドが終わった後に、メッセージボックスを出したい。画面は、操作したい。って場合です。
では、C#5 で追加されたasync/awaitを使って書いてます。
private async void button1_Click( object sender, EventArgs e )
{
var msg = await HeavyCalcurate_Async();
MessageBox.Show( msg );
}
private async Task<String> HeavyCalcurate_Async()
{
var task = await new TaskFactory().StartNew( ()=>
{
for( var i = 0; i < 10; i++ )
{
System.Threading.Thread.Sleep( 2000 );
}
return "完了";
} );
return task;
}
コードが簡単になっていますね。
上に書いた処理待ちのコードが、だいぶすっきりしています。
このように書くだけで、Taskが実行され、そのあとにちゃんとメッセージボックスが出ます。
さらに、一番大事なのは、処理待ちの間も問題なくGUIを動かしたりできます。
ってわけで、1つ賢くなったのですが、一つ残念なことがありました。
C# 5が当たり前な世代では、async/awaitがない場合にはなんて考えないかも?!
使うのが当たり前でしょって思ったそこのあなた!
どうか、筆者を年寄り扱いしないでくださいね。そこのところ、よろしくお願いいたします。
おまけ
コンパイラによるラムダ式の展開に絡みますが、上記コードをコンパイルしたコードを見てみると、
DebugとReleaseでだいぶコードが異なるので面白いかも。
0 件のコメント:
コメントを投稿