2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

たくさんの非同期処理をTask.Run()させたいけど同時に動かない

Posted at

参考にさせて頂いた記事

言い訳

実際には業務中に問題が出てきてサンプルソースは都合よく作ったものなので悪しからず

.NETのばーじょん

.NET 8.0

とりあえずやってみる

// めちゃくちゃHello, Worldさせたい
List<Task> helloWorldTaskList = new List<Task>();

// とりあえず100個のTaskを生成してみる
for (int i = 0; i < 100; i++)
{
    int taskNo = i;

    helloWorldTaskList.Add(Task.Run(() =>
    {
        for (int j = 0; j < 10000000; j++)
        {
            Console.WriteLine($"Task{taskNo}:Hello, World!");
        }
    }));
}

// すべてのタスクの終了待ち
await Task.WhenAll(helloWorldTaskList);

Console.WriteLine("終了");

int taskNoを使用する理由はさておき、実行しているタスクが偏っている気がするので、初回起動のログを仕込んで確認してみる。

List<Task> taskList = new List<Task>();
Stopwatch sw = Stopwatch.StartNew();

// 15個のTaskを生成してみる
for (int i = 0; i < 15; i++)
{
    int taskNo = i;

    taskList.Add(Task.Run(() =>
    {
        Console.WriteLine($"{sw.ElapsedMilliseconds}ms後 Task{taskNo}:★起動");
        Thread.Sleep(5000);
    }));
}

Console.WriteLine($"{sw.ElapsedMilliseconds}ms後 Task生成終了");

await Task.WhenAll(taskList);

Console.WriteLine("終了");

実行してみる。

26ms後 Task2:★起動
35ms後 Task生成終了
26ms後 Task0:★起動
26ms後 Task1:★起動
26ms後 Task3:★起動
26ms後 Task4:★起動
27ms後 Task5:★起動
27ms後 Task6:★起動
38ms後 Task7:★起動
823ms後 Task8:★起動
1338ms後 Task9:★起動
1855ms後 Task10:★起動
2859ms後 Task11:★起動
3873ms後 Task12:★起動
4381ms後 Task13:★起動
5052ms後 Task14:★起動
終了

8つ目までは早く実行されているけど、15個目についてはかなり後に実行されている。

ThreadPoolについて

へんしゅうちゅう

ThreadPool.SetMinThreads()を使用してみる

// ↓ ここを追加 ↓
int workerThread;
int completionPortThread;
ThreadPool.GetMinThreads(out workerThread, out completionPortThread);
Console.WriteLine($"WorkerThread:{workerThread} -> 15");
ThreadPool.SetMinThreads(15, completionPortThread);
// ↑ ここを追加↑

List<Task> taskList = new List<Task>();
Stopwatch sw = Stopwatch.StartNew();

for (int i = 0; i < 15; i++)
{
    int taskNo = i;

    taskList.Add(Task.Run(() =>
    {
        Console.WriteLine($"{sw.ElapsedMilliseconds}ms後 Task{taskNo}:★起動");
        Thread.Sleep(5000);
    }));
}

DateTime curTime = DateTime.Now;
Console.WriteLine($"{sw.ElapsedMilliseconds}ms後 Task生成終了");

await Task.WhenAll(taskList);

Console.WriteLine("終了");

検証結果

WorkerThread:8 -> 15
9ms後 Task2:★起動
9ms後 Task0:★起動
9ms後 Task1:★起動
10ms後 Task3:★起動
14ms後 Task4:★起動
19ms後 Task5:★起動
24ms後 Task6:★起動
30ms後 Task7:★起動
34ms後 Task9:★起動
34ms後 Task8:★起動
39ms後 Task10:★起動
43ms後 Task生成終了
43ms後 Task11:★起動
48ms後 Task12:★起動
53ms後 Task13:★起動
57ms後 Task14:★起動
終了

先ほどと比べて最後のタスクの起動速度が大幅に速くなった。

後記

へんしゅうちゅう

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?