【C#】WindowsFormsアプリで見る非同期処理
非同期処理は、プログラムが何か長い時間がかかる作業をしている間に、他の作業を同時に行えるようにする方法です。これは、例えばウェブページの読み込みやファイルのダウンロード、データベースからの情報の取得など、時間のかかる操作を行う際に非常に役立ちます。
非同期処理を使うことで、プログラムは次のように振る舞います。
- 通常の(同期)処理:一つの作業が終わるまで、次の作業に進めない。作業が遅い場合、全体のプログラムの動作が停止する可能性がある。
- 非同期処理:プログラムは重い作業を別のスレッド(仮想の作業スペース)で実行し、メインのスレッドでは他の作業を進める。つまり、重い作業が終わるのを待たずに、他の仕事も同時に進められる。
C#で非同期処理を使うには、async
とawait
というキーワードを使います。
同期と非同期の比較サンプル
サンプル動画
同期ボタンを押すと、UIがロックされているのがわかります
ロックとは、他のUI(ボタンなど)が押せない状態です
処理が終わるまで待たないといけません
非同期ボタンを押した時は、他のボタンも押すことができロックされないのがわかります
デザイン
2つのボタンと、2つのラベルを配置します
それぞれのボタンには、クリックした時のイベントハンドラを登録します
コード
namespace AsyncSample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void buttonBlocking_Click(object sender, EventArgs e)
{
// ボタンをクリックしたら、5秒間の間、UIはブロックされます
Thread.Sleep(5000);
labelBlocking.Text = "ブロックされました";
}
private async void buttonNonBlocking_Click(object sender, EventArgs e)
{
// ボタンをクリックしたら、5秒間の処理を非同期で実行し、UIはブロックされません
labelNonBlocking.Text = "非同期処理中...";
await Task.Delay(5000);
labelNonBlocking.Text = "非同期処理完了";
}
}
}
private async void buttonNonBlocking_Click(object sender, EventArgs e)
: このメソッドは、buttonNonBlocking
という名前のボタンがクリックされたときに呼び出されます。このメソッドは非同期メソッドであり、async
キーワードで修飾されています。labelNonBlocking.Text = "非同期処理中...";
:labelNonBlocking
という名前のラベルのテキストを「非同期処理中…」に設定します。これにより、ユーザーに非同期処理が進行中であることを通知します。await Task.Delay(5000);
:Task.Delay
メソッドを使用して、非同期で5秒間の待機を行います。これにより、UIはブロックされませんが、5秒間の間に他の操作が実行されないことを保証します。この待機が終了すると、次の行が実行されます。labelNonBlocking.Text = "非同期処理完了";
: 待機が終了した後、labelNonBlocking
のテキストを「非同期処理完了」に設定し、非同期処理が正常に完了したことをユーザーに通知します。
Thread.Sleep(5000)
と await Task.Delay(5000)
の違い
Thread.Sleep(5000)
と await Task.Delay(5000)
は、両方とも一定の時間(ここでは5000ミリ秒、つまり5秒)の間待機するために使用されるコードフラグメントですが、その動作と使用方法には重要な違いがあります。
Thread.Sleep(5000)
:Thread.Sleep
メソッドは、カレントスレッド(実行中のスレッド)を指定された時間だけ一時停止します。- これは同期的な操作であり、カレントスレッドが5秒間ブロックされ、その間他のタスクやスレッドは処理できません。したがって、UIスレッドやメインスレッドなどのスレッドで
Thread.Sleep
を使用すると、アプリケーションの応答性が低下する可能性があります。非UIスレッドでの使用は影響が少ないですが、他のスレッドが同じリソースにアクセスする場合には注意が必要です。
await Task.Delay(5000)
:Task.Delay
メソッドは、非同期的な待機を提供し、非ブロッキングです。await
キーワードと一緒に使用されることが一般的で、Task.Delay
の結果を待機し、その間に他のタスクやスレッドが処理できるようにします。つまり、カレントスレッドがブロックされないため、アプリケーションの応答性が維持されます。- このアプローチは、UIスレッドやメインスレッドでの使用に適しており、非同期プログラミングパターンと組み合わせて、アプリケーションのスムーズな動作を確保するのに役立ちます。
総括すると、Thread.Sleep
は同期的でブロッキングな待機方法であり、Task.Delay
は非同期で非ブロッキングな待機方法です。非同期プログラミングのコンテキストでは、Task.Delay
を使用することをお勧めします。
非同期の時、同じボタンを連続で押されないようにしたい
サンプル動画
非同期ボタンをクリックするとボタンが無効化されます
処理が終わると有効化されます
コード
private async void buttonNonBlocking_Click(object sender, EventArgs e)
{
buttonNonBlocking.Enabled = false;
// ボタンをクリックしたら、5秒間の処理を非同期で実行し、UIをブロックしない
labelNonBlocking.Text = "非同期処理中...";
await Task.Delay(5000);
labelNonBlocking.Text = "非同期処理完了";
buttonNonBlocking.Enabled = true;
}
このコードは、C#のWindows Formsアプリケーションで使用されることを想定しています。コードの目的は、ボタンをクリックした際にUIをブロックせずに非同期処理を実行することです。
以下はコードの詳細な説明です:
private async void buttonNonBlocking_Click(object sender, EventArgs e)
: このメソッドは、buttonNonBlocking
という名前のボタンがクリックされたときに呼び出されます。このメソッドは非同期メソッドであり、async
キーワードで修飾されています。buttonNonBlocking.Enabled = false;
: ボタンをクリックした直後、buttonNonBlocking
ボタンを無効にします。これにより、ユーザーが連続してボタンをクリックして処理を開始するのを防ぎます。labelNonBlocking.Text = "非同期処理中...";
:labelNonBlocking
という名前のラベルのテキストを「非同期処理中…」に設定します。これにより、ユーザーに非同期処理が進行中であることを通知します。await Task.Delay(5000);
:Task.Delay
メソッドを使用して、非同期で5秒間の待機を行います。これにより、UIはブロックされませんが、5秒間の間に他の操作が実行されないことを保証します。この待機が終了すると、次の行が実行されます。labelNonBlocking.Text = "非同期処理完了";
: 待機が終了した後、labelNonBlocking
のテキストを「非同期処理完了」に設定し、非同期処理が正常に完了したことをユーザーに通知します。buttonNonBlocking.Enabled = true;
: 最後に、buttonNonBlocking
ボタンを再度有効にし、ユーザーが再びボタンをクリックできるようにします。
このコードは、UIを非同期的に更新し、ブロックしないようにする一般的なパターンを示しています。ユーザーがボタンをクリックしても、アプリケーションは応答性を維持し、非同期処理をバックグラウンドで実行します。
作成したメソッド中で実行したい
上記サンプルをメソッド化しました
private async void buttonNonBlocking_Click(object sender, EventArgs e)
{
labelNonBlocking.Text = "非同期処理中...";
await WaitMethodAsync();
labelNonBlocking.Text = "非同期処理完了";
}
private async Task WaitMethodAsync()
{
await Task.Delay(5000);
}
戻り値を取得
private async void buttonNonBlocking_Click(object sender, EventArgs e)
{
// ボタンをクリックしたら、5秒間の処理を非同期で実行し、UIをブロックしない
labelNonBlocking.Text = "非同期処理中...";
var result = await WaitMethodAsync(); // 非同期メソッドを使用
labelNonBlocking.Text = result;
}
private async Task<string> WaitMethodAsync()
{
await Task.Delay(5000); // 非同期待機を使用してUIスレッドをブロックしない
return "おわり";
}
ディスカッション
コメント一覧
まだ、コメントがありません