[.NET Framework] 非同期処理とUIスレッドとのコンテキスト遷移の歴史

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

[.NET Framework] 非同期処理とUIスレッドとのコンテキスト遷移の歴史

投稿記事 by YuO » 12年前

http://dixq.net/forum/viewtopic.php?f=3&t=12236に書こうとして,取りやめた内容ですが,せっかくなのでこちらに書いておきます。

.NET Frameworkにはいくつかの非同期実行のための仕組みがあります。
同一のことを繰り返すのであればタイマーでよいのですが,状態遷移を含む場合はタイマーが最適とは限らなくなります。

というわけで,非同期実行とスレッドコンテキスト遷移の.NET Frameworkにおける歴史です。
キーワードは書いてあるので,適当に探すための元になればと。
サンプルは,タイマーをあえて非同期実行で書く例です。
  • .NET 1.0/1.1
    Begin~/End~の対とコールバックデリゲートによる非同期処理 (APM)
    Control.Invokeによるコンテキスト遷移

    CODE:

    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によるコンポーネント化

    CODE:

    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)

    CODE:

    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パターンを実装)

    CODE:

    private async void button1_Click (object sender, EventArgs e)
    {
        button1.Enabled = false;
        for (var i = 0; ; i = (i + 1) % 10000)
        {
            await Task.Delay(TimeSpan.FromSeconds(1.0));
            this.Text = i.ToString();
        }
    }
添付ファイル

[拡張子 zip は無効化されているため、表示できません]


コメントはまだありません。