0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【C#】非同期で処理を実施する方法

Posted at

結論

Task.Runasyncawaitを使います。

非同期ソース例(Task.Run)
Console.WriteLine("処理を開始");

var task = Task.Run(() =>
{
    //時間がかかる処理
    for (int i = 0; i < 5; i++)
    {
        Console.WriteLine("非同期処理中...");
        Thread.Sleep(1000);
    }
});

//非同期処理が完了するまで待機
while (!task.IsCompleted)
{
    Console.WriteLine("処理中...");
    Thread.Sleep(1000);
}

Console.WriteLine("処理が終了");

以下に事例別に解説します。

解説

結論の非同期ソース例を実行すると下記のような出力になります。
image.png

非同期処理を実施しながら他の処理をしたい場合

Task.Runを使います。
こちらは結論の非同期処理ソース例を使用することで再現できます。
細かく解説していきます。
改めて解説するソースコードは下記になります。

非同期処理を実施しながら他の処理をしたい場合のソース例
Console.WriteLine("処理を開始");

var task = Task.Run(() =>
{
    //時間がかかる処理
    for (int i = 0; i < 5; i++)
    {
        Console.WriteLine("非同期処理中...");
        Thread.Sleep(1000);
    }
});

//非同期処理が完了するまで待機
while (!task.IsCompleted)
{
    Console.WriteLine("処理中...");
    Thread.Sleep(1000);
}

Console.WriteLine("処理が終了");

非同期で実行している箇所は下記になります。

非同期実行している箇所
var task = Task.Run(() =>
{
    //時間がかかる処理
    for (int i = 0; i < 5; i++)
    {
        Console.WriteLine("非同期処理中...");
        Thread.Sleep(1000);
    }
});

Task.Run()を使用することでタスク(非同期処理)を実行することができます。
タスクの状態はtask変数に格納されています。task変数はTask型です。
Task型で個人的によく使うプロパティと関数は下記になります。

種類 名前 内容
プロパティ IsCompleted タスクが完了したかどうかを示す値を取得します。
関数 Delay 非同期で待機します。(Thread.Sleepの非同期版)
関数 Run タスクを実行してTask型のオブジェクトを返します。
そして、非同期中に実行している箇所は下記になります。
非同期処理と同時進行している箇所
while (!task.IsCompleted)
{
    Console.WriteLine("処理中...");
    Thread.Sleep(1000);
}

Console.WriteLine("処理が終了");

ここではtask変数のIsCompletedプロパティを確認してfalse(実行中)であれば処理中...と出力しています。そして、IsCompletedプロパティを確認してtrue(実行終了)になればwhileループを抜けて処理が終了と出力しています。

関数を非同期で実行したい場合

asyncawaitを使用します。
下記はWinFormアプリケーションで現在時刻を非同期で更新するソースコードです。

ソース例
private CancellationTokenSource tokenSource;
private CancellationToken cancelToken;

private async void buttonStart_Click(object sender, EventArgs e)
{
    //現在時刻の更新処理を開始する
    tokenSource = new CancellationTokenSource();
    cancelToken = tokenSource.Token;
    await UpdateDateTimeAsync(cancelToken);
}

private void buttonEnd_Click(object sender, EventArgs e)
{
    //現在時刻の更新処理を停止する。
    tokenSource.Cancel();
}

private async Task UpdateDateTimeAsync(CancellationToken cancelToken)
{
    //停止リクエストが来たら終了する。
    while (!cancelToken.IsCancellationRequested)
    {
        labelDateTimeNow.Text = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
        await Task.Delay(1000);
    }
}

実行した結果は下記の画像です。非同期処理なのでフォームの位置を移動できます。
image.png

現在時刻更新開始ボタンを押下するとbuttonStart_Click関数が実行されます。
buttonStart_Click関数ではUpdateDateTimeAsync関数を非同期処理で実行を開始しています。
関数にasyncをつけることでawaitを実施できるようになります。awaitを関数の前につけるとその関数を非同期で実施している間は呼び出し関数に処理を返します。そしてその関数の非同期処理が終了した段階でawait後のソースコードを実行します。
ソース箇所は下記になります。

ソース箇所
private async void buttonStart_Click(object sender, EventArgs e)
{
    //現在時刻の更新処理を開始する
    tokenSource = new CancellationTokenSource();
    cancelToken = tokenSource.Token;
    await UpdateDateTimeAsync(cancelToken);
}

現在時刻更新終了ボタンを押下するとbuttonEnd_Click関数が実行されます。
buttonEnd_Click関数ではbuttonStart_Click関数で実行を開始したUpdateDateTimeAsync関数に対してキャンセルリクエストを送信しています。
ソース箇所は下記になります。

ソース箇所
private void buttonEnd_Click(object sender, EventArgs e)
{
    //現在時刻の更新処理を停止する。
    tokenSource.Cancel();
}

UpdateDateTimeAsync関数ではフォームのラベルを1秒おきに現在時刻に更新しています。
もし、実行している途中にキャンセルリクエストが届いている場合はwhileループを抜けて非同期処理を終了しています。
ソース箇所は下記になります。

ソース箇所
private async Task UpdateDateTimeAsync(CancellationToken cancelToken)
{
    //停止リクエストが来たら終了する。
    while (!cancelToken.IsCancellationRequested)
    {
        labelDateTimeNow.Text = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
        await Task.Delay(1000);
    }
}

以上です。

非同期処理に関する参考サイト

0
4
0

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
  3. You can use dark theme
What you can do with signing up
0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?