C#非同期処理ことはじめ

ようやくC#の非同期処理を使い始めたので、メモしておきます。



デスクトップアプリを作っているときに、ボタンを押して時間がかかる処理があると、処理が進んでいることを表示したいと云うことが多いと思います。

そこで、下記のようなコードを書くわけですが、実行すると、ラベルは「0」にも「1」にもならず、すべての処理が終わった後に「2」が表示されるという不本意な動作となります。

  1.         private void button3_Click(object sender, EventArgs e)
  2.         {
  3.             var sql = "waitfor delay '00:00:05'";
  4.  
  5.             this.labelStatus.Text = "0";
  6.  
  7.             DataTable dt1 = mm40Database.doSqlQuery(sql);
  8.             this.labelStatus.Text = "1";
  9.  
  10.             DataTable dt2 = mm40Database.doSqlQuery(sql);
  11.             this.labelStatus.Text = "2";
  12.         }

この場合、DoEventsメソッドを呼ぶというのが解決策のひとつでした。下記のようにすると、ラベルには「0」、「1」、「2」と順に表示されます。

  1.         private void button2_Click(object sender, EventArgs e)
  2.         {
  3.             var sql = "waitfor delay '00:00:05'";
  4.  
  5.             this.labelStatus.Text = "0";
  6.             Application.DoEvents();
  7.  
  8.             DataTable dt1 = mm40Database.doSqlQuery(sql);
  9.             this.labelStatus.Text = "1";
  10.             Application.DoEvents();
  11.  
  12.             DataTable dt2 = mm40Database.doSqlQuery(sql);
  13.             this.labelStatus.Text = "2";
  14.         }

別の解決策が非同期処理で、時間がかかる処理を非同期で実行してawaitで終了を待ちます。下記のように。

  1.         async private void button1_Click(object sender, EventArgs e)
  2.         {
  3.             var sql = "waitfor delay '00:00:05'";
  4.  
  5.             this.labelStatus.Text = "0";
  6.  
  7.             DataTable dt1 = await Task<DataTable>.Run(() => mm40Database.doSqlQuery(sql));         // 非同期!
  8.             this.labelStatus.Text = "1";
  9.  
  10.             DataTable dt2 = await Task<DataTable>.Run(() => mm40Database.doSqlQuery(sql));         // 非同期!
  11.             this.labelStatus.Text = "2";
  12.         }

DoEventsメソッドを呼ばなくてもラベルは「0」、「1」、「2」と表示されます。すごく自然でよいね。まあ、「await Task<Type>.Run(() => メソッド呼び出し)」が見慣れないコードで、すごく不自然かもしれない。

これはこういうものだと、今は思っておく。時間がかかるメソッド呼び出しを非同期にしたいときは、そこをこういう具合に書き換えると。

たぶん、ほとんどの場合は、この方法で対応できるのではないかな。

ラムダ式に慣れていないと訳が分からないわな。



コメント

このブログの人気の投稿

varchar をデータ型 numeric に変換中に、算術オーバーフロー エラーが発生しました。