search
LoginSignup
21

More than 5 years have passed since last update.

posted at

updated at

Organization

Windows Formアプリケーションでの非同期処理

Timerって便利だけれども

Windows FormアプリケーションではTimerコンポーネントがあるので一定間隔の処理を行うのは便利ですね。
ただし、このTimerはGUIスレッドで動作するので、重い処理を実行するとGUIのイベントループも止まってしまうために、ウィンドウが動かせなかったりします。

以下だと、10秒間固まってしまうわけです。

    private void timerHoo_Tick(object sender, EventArgs e)
    {
        Thread.Sleep(10000);
    }

間違った解決

それを嫌ってタスクに処理を任せたくなるわけですが、それにも問題があります。

    private void timerHoo_Tick(object sender, EventArgs e)
    {
        Debug.WriteLine("start");
        Task.Run(() =>
        {
            Debug.WriteLine("thread start");
            Thread.Sleep(10000);
            Debug.WriteLine("thread end");
        });
        Debug.WriteLine("end");
    }

これを実行するとタスク生成だけしてTick関数がさっさと抜けていき、Timer間隔が短いと次々とタスクが生成されてしまいます。

start
end
thread start
start
end
thread start
start
end
thread start
start
end
thread start
thread end        // <-いつの???

async/await で解決

そこで登場するのが C#5.0 から使える async/await ですね。

    private async void timerHoo_Tick(object sender, EventArgs e)
    {
        Debug.WriteLine("start");
        await Task.Run(() =>
        {
            Debug.WriteLine("thread start");
            Thread.Sleep(10000);
            Debug.WriteLine("thread end");
        });
        Debug.WriteLine("end");
    }

平和です。

start
thread start
thread end
end
start
thread start
thread end
end
start
thread start
thread end
end

お詳しい解説はこちら

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
21