none
async/awaitの方法について RRS feed

  • 質問

  • .NET Framework 4.5のasync/awaitを使用することで、UIが固まる問題等を簡単に回避することができますが、.NET Framework 4.0では以下のコード(.NET Framework 4.5で作成したコードになります)の場合、どのように実装するのでしょうか。

        public partial class Form1 : Form
        {
            private string buffer;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private async void button1_Click(object sender, EventArgs e)
            {
                await TestMehodAsync();
                textBox1.Text = buffer;
            }
    
            private Task TestMehodAsync()
            {
                return Task.Run(() =>
                {
                    System.Threading.Thread.Sleep(10000);
                    buffer = "result";
                });
            }
        }
    


    2018年2月19日 1:14

回答

  • 開発環境がVisual Studio 2012以降であれば、Microsoft Bcl AsyncをNugetからインストールすることで、async/awaitキーワードを使用できるようになるかと思います。

    // 配布時に多少落とし穴があるそうですが。参照:http://blog.xin9le.net/entry/2012/12/26/125214

    2018年2月19日 2:10
  • 参考までに、.NET Framework 4.0がプリインストールされたOSは存在せず、また.NET Framework 4.0~4.5.1はすでにサポートが終了しています。つまり、4.0で動作するのはサポート終了済みバージョンを故意にインストールしている環境に限られます。

    これからの実装について検討されるのであれば、4.0は対象外とした方がよろしいかと。

    # ところで.NET Micro Frameworkの話題でしょうか?

    2018年2月19日 2:18
  •     public partial class Form1 : Form
        {
            private string buffer;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                TestMehodAsync().ContinueWith(t =>
                    {
                        textBox1.Text = buffer;
                    }, TaskScheduler.FromCurrentSynchronizationContext());
            }
    
            private Task TestMehodAsync()
            {
                return Task.Factory.StartNew(() =>
                {
                    System.Threading.Thread.Sleep(5000);
                    buffer = "result";
                });
            }
        }

    こんな方法もあります。

    2018年2月19日 6:35

すべての返信

  • 一つの案ですが、Task クラスを使用すると下記のように記述できます。

    using System;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            delegate void SetTextCallback(string text);
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                Task.Factory.StartNew(() =>
                {
                    System.Threading.Thread.Sleep(10000);
                    SetText("result");
                });
            }
    
            private void SetText(string text)
            {
                if (this.textBox1.InvokeRequired)
                {
                    SetTextCallback d = new SetTextCallback(SetText);
                    Invoke(d, new object[] { text });
                }
                else
                {
                    textBox1.Text = text;
                }
            }
        }
    }

    参考サイト:
    http://ufcpp.net/study/csharp/misc_task.html
    https://msdn.microsoft.com/ja-jp/library/ms171728%28v=vs.110%29.aspx

    2018年2月19日 1:56
  • 以下辺りを読まれて、非同期処理の歴史を把握されると良いと思います。

    第1回 .NET開発における非同期処理の基礎と歴史
    http://www.atmarkit.co.jp/fdotnet/chushin/masterasync_01/masterasync_01_02.html


    ★良い回答には質問者は回答済みマークを、閲覧者は投票を!

    2018年2月19日 2:03
  • デリゲートを使用してコールバック後にUIスレッドを操作することは把握しておりますが、本質問の意図としましては.NET4.5でのasync/awaitのように、button1_Ckick(同期処理)上で非同期処理完了を待ち合わせる(ように見せている)ことはできないのかと思い質問させて頂きました。

    .NET 4.0での非同期処理はコールバックで完了を通知して、そのうえでUIスレッドを操作するしか無いのでしょうか。

    2018年2月19日 2:06
  • 開発環境がVisual Studio 2012以降であれば、Microsoft Bcl AsyncをNugetからインストールすることで、async/awaitキーワードを使用できるようになるかと思います。

    // 配布時に多少落とし穴があるそうですが。参照:http://blog.xin9le.net/entry/2012/12/26/125214

    2018年2月19日 2:10
  • 参考までに、.NET Framework 4.0がプリインストールされたOSは存在せず、また.NET Framework 4.0~4.5.1はすでにサポートが終了しています。つまり、4.0で動作するのはサポート終了済みバージョンを故意にインストールしている環境に限られます。

    これからの実装について検討されるのであれば、4.0は対象外とした方がよろしいかと。

    # ところで.NET Micro Frameworkの話題でしょうか?

    2018年2月19日 2:18
  • 参考までに、.NET Framework 4.0がプリインストールされたOSは存在せず、また.NET Framework 4.0~4.5.1はすでにサポートが終了しています。つまり、4.0で動作するのはサポート終了済みバージョンを故意にインストールしている環境に限られます。

    これからの実装について検討されるのであれば、4.0は対象外とした方がよろしいかと。

    OSのサポートは認識しておりましたが、.NET Frameworkにもサポート期間があるのは知りませんでした。

    4.0は対象外として検討致します。

    # ところで.NET Micro Frameworkの話題でしょうか?

    失礼しました。選択する項目を誤っておりました。

    2018年2月19日 2:32
  • ありがとうございます。

    Microsoft Bcl Asyncを利用する方法で検討致します。

    2018年2月19日 2:34
  •     public partial class Form1 : Form
        {
            private string buffer;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                TestMehodAsync().ContinueWith(t =>
                    {
                        textBox1.Text = buffer;
                    }, TaskScheduler.FromCurrentSynchronizationContext());
            }
    
            private Task TestMehodAsync()
            {
                return Task.Factory.StartNew(() =>
                {
                    System.Threading.Thread.Sleep(5000);
                    buffer = "result";
                });
            }
        }

    こんな方法もあります。

    2018年2月19日 6:35
  •     public partial class Form1 : Form
        {
            private string buffer;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                Task.Factory.StartNew(() =>
                {
                    System.Threading.Thread.Sleep(5000);
                    buffer = "result";
                }).ContinueWith(t =>
                {
                    textBox1.Text = buffer;
                }, TaskScheduler.FromCurrentSynchronizationContext());
            }
        }
    
    こっちの方がわかりやすいかな?
    2018年2月19日 6:38
  • ご回答ありがとうございます。

    ContinueWithとTask.Scheduler.FromCurrentSyncronizationContextで非同期完了時にUIスレッドと同期しているということでしょうか。

    2018年2月19日 16:45
  • ContinueWithとTask.Scheduler.FromCurrentSyncronizationContextで非同期完了時にUIスレッドと同期しているということでしょうか。

    そうですね、ContinueWithがあるタスク終了後に別のタスクを続けて実行する仕組みで、FromCurrentSyncronizationContextが、その後続タスクをどのようにスケジュールするかのオプションになります。

    FromCurrentSyncronizationContextは、ContinueWithでタスク投入を呼び出すスレッド(つまりUIスレッド)から見て、現在の同期コンテキストで実行しなさいという指定、つまりはUIスレッドで実行しなさいという指定になります。

    2018年2月20日 3:00