■ はじめに
https://dk521123.hatenablog.com/entry/2010/12/12/164101
https://dk521123.hatenablog.com/entry/2010/12/25/221009
https://dk521123.hatenablog.com/entry/2010/10/22/101350
の続き。
■ 基本的な流れ
1)非同期で呼び出すメソッドと同じシグネチャを持つデリゲートを用意 2)用意したデリゲートから BeginInvoke メソッドにより、非同期実行を開始 3)BeginInvoke 指定の際、非同期処理が終了したときのメソッド(例:EndInvoke())を指定 => 以下の「■ サンプル」の「例1」のコメントと対比してみるといいかも
■ サンプル
例1:処理を別スレッドで実行 例2:処理を別スレッドに処理状況をみて実行
例1:処理を別スレッドで実行
キーワード
* IAsyncResult * BeginInvoke/EndInvoke()
Form1.cs
using System; using System.Windows.Forms; namespace SampleForm { public partial class Form1 : Form { // 【1】 非同期で呼び出すメソッド(DelegatingMethod())と同じシグネチャを持つデリゲートを用意 // 非同期実行するためのデリゲート private delegate string SampleDelegate(int sleep, string format); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { // 実行するデリゲートを作成 SampleDelegate sampleDelegate = new SampleDelegate(this.DelegatingMethod); // 【2】 用意したデリゲートから BeginInvoke メソッドにより、非同期実行を開始 // 非同期で呼び出す IAsyncResult asyncResult = sampleDelegate.BeginInvoke(5000, "yyyy/MM/dd", null, null); this.label1.Text = "Called BeginInvoke()"; // 【3】 BeginInvoke 指定の際、非同期処理が終了したときのメソッド(例:EndInvoke())を指定 // 処理結果取得 string resultFromDelegatingMethod = sampleDelegate.EndInvoke(asyncResult); this.label2.Text = "Called EndInvoke() : Today is " + resultFromDelegatingMethod; } // 非同期させたい(重たい)処理 private string DelegatingMethod(int sleep, string format) { System.Threading.Thread.Sleep(sleep); return DateTime.Now.ToString(format); } } }
出力結果
【ボタン押下直後】 Called BeginInvoke() label2 【ボタン押下5秒後】 Called BeginInvoke() Called EndInvoke() : Today is 2013/05/27
例2:処理を別スレッドに処理状況をみて実行
キーワード
* IAsyncResult * AsyncWaitHandle.WaitOne() * IAsyncResult.IsCompleted
Form1.cs
using System; using System.Windows.Forms; namespace SampleForm { public partial class Form1 : Form { // 非同期実行するためのデリゲート private delegate string SampleDelegate(int sleep, string format); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { // 実行するデリゲートを作成 SampleDelegate sampleDelegate = new SampleDelegate(this.DelegatingMethod); // 非同期で呼び出す。 IAsyncResult asyncResult = sampleDelegate.BeginInvoke(5000, "yyyy/MM/dd", null, null); this.label1.Text = "Called BeginInvoke()"; // 2秒だけ処理を中断して別スレッドの計算を待つ asyncResult.AsyncWaitHandle.WaitOne(2000); if (asyncResult.IsCompleted) { // ここは実行されない(処理に5秒かかるが上で2秒しかまってないから実行されず) this.label2.Text = "Still Running?"; } else { this.label3.Text = "Yes, Still Running..."; } this.label4.Text = "Before calling AsyncWaitHandle.WaitOne..."; // 別スレッドの処理が終わるまで待つ asyncResult.AsyncWaitHandle.WaitOne(); this.label4.Text = "Called AsyncWaitHandle.WaitOne..."; if (asyncResult.IsCompleted) { // 処理結果取得 string resultFromDelegatingMethod = sampleDelegate.EndInvoke(asyncResult); this.label5.Text = "Today is " + resultFromDelegatingMethod; } } // 非同期させたい(重たい)処理 private string DelegatingMethod(int sleep, string format) { System.Threading.Thread.Sleep(sleep); return DateTime.Now.ToString(format); } } }
出力結果
【ボタン押下直後】 Called BeginInvoke() label2 label3 label4 label5 【ボタン押下2秒後】 Called BeginInvoke() label2 label3 Before calling AsyncWaitHandle.WaitOne... label5 【ボタン押下5秒後】 Called BeginInvoke() label2 Yes, Still Running Called AsyncWaitHandle.WaitOne... Today is 2013/05/27
参考文献
http://d.hatena.ne.jp/gsf_zero1/20090312/p1
http://d.hatena.ne.jp/teramonagi/20110820/1313838406
http://acha-ya.cocolog-nifty.com/blog/2010/09/post-fe36.html
http://n2-csharp.blogspot.jp/2009/09/blog-post_26.html
関連記事
Delegate / Event ~ 入門編 / Delegate ~
https://dk521123.hatenablog.com/entry/2010/12/12/164101
Delegate / Event ~ 入門編 / Event ~
https://dk521123.hatenablog.com/entry/2010/12/25/221009