.NET Frameworkにはいくつかの非同期実行のための仕組みがあります。
同一のことを繰り返すのであればタイマーでよいのですが,状態遷移を含む場合はタイマーが最適とは限らなくなります。
というわけで,非同期実行とスレッドコンテキスト遷移の.NET Frameworkにおける歴史です。
キーワードは書いてあるので,適当に探すための元になればと。
サンプルは,タイマーをあえて非同期実行で書く例です。
- .NET 1.0/1.1
Begin~/End~の対とコールバックデリゲートによる非同期処理 (APM)
Control.Invokeによるコンテキスト遷移private delegate void VoidAction (); private delegate void StringAction (string s); private void button1_Click (object sender, EventArgs e) { button1.Enabled = false; VoidAction action = new VoidAction(MainFunction); action.BeginInvoke(null, null); } private void SetText (string s) { this.Text = s; } private void MainFunction () { StringAction setText = new StringAction(SetText); for(int i = 0; ; i = (i + 1) % 10000) { Thread.Sleep(TimeSpan.FromSeconds(1.0)); Invoke(setText, i.ToString()); } }
- .NET 2.0
コールバックを呼び出しスレッドコンテキストでイベント発生によって行う非同期処理 (EAP)
他コンテキストでの実行を行うためのSynchronizationContext
BackgroundWorkerによるコンポーネント化private void button1_Click (object sender, EventArgs e) { button1.Enabled = false; backgroundWorker1.RunWorkerAsync(); } private void backgroundWorker1_DoWork (object sender, DoWorkEventArgs e) { for (int i = 0; ; i = (i + 1) % 10000) { Thread.Sleep(TimeSpan.FromSeconds(1.0)); backgroundWorker1.ReportProgress(i); } } private void backgroundWorker1_ProgressChanged (object sender, ProgressChangedEventArgs e) { this.Text = e.ProgressPercentage.ToString(); }
- .NET 4.0
データ並列に対するPLINQ
Taskを使った非同期処理 (TAP)private void button1_Click (object sender, EventArgs e) { button1.Enabled = false; StartNewTask(0, TaskScheduler.FromCurrentSynchronizationContext()); } private void StartNewTask (int i, TaskScheduler scheduler) { Task.Factory.StartNew(() => { Thread.Sleep(TimeSpan.FromSeconds(1.0)); }, Task.Factory.CancellationToken, TaskCreationOptions.None, TaskScheduler.Default).ContinueWith(t => { Text = i.ToString(); StartNewTask((i + 1) % 10000, TaskScheduler.Current); }, scheduler); }
- .NET 4.5
Awaiterパターンによるasync/await (実際にはTaskがAwaiterパターンを実装)