質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

解決済

非同期処理の練習、Task.Run後におかしな値を返す。

Sado
Sado

総合スコア89

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

2回答

0評価

0クリップ

336閲覧

投稿2022/08/08 10:48

前提

c#のtaskと非同期処理の理解のため、別スレッドに処理を投げるコードを書いてみたのですが意図した結果が得られません。
各ポイントごとにログを出してみたところ、Task.Run()直後からおかしな値を返す挙動をします。

発生している問題

おおまかなログの発生順は意図した通り出力できているのですが、返してくる値がすべて「5」なのが問題です。
私としては「0,1,2,3,4」と出力して欲しいのですが、加算式にもしていないのに何故かループ回数と同じ「5」が5回出力されます。
この「5」に置き換わるタイミングが、Task.Runを使用している箇所HeavyProc()からです。
ここまでの検証で、なぜ「5」が出力されるのか全く見当がつかない状態です。

また、非同期処理なので多少ログの実行順にばらつきが生まれるのは理解できるのですが、色分けの処理がうまく実行されず、緑色から解除されない事が稀にあります。
色を変えてログ処理するメソッドは、すぐに元の色に戻すように書いたつもりですが「非同期処理」においてはこれでは不十分なのでしょうか。
色変えのタイミングに関してはまだ自分の中でも検証が不十分ですので、こういった問題が発生することだけ先に示しておきます。

dotnet run [Main] start... [RunHeavyProcs] i = 0 [RunHeavyProcs] i = 1 [RunHeavyProcs] i = 2 [RunHeavyProcs] i = 3 [RunHeavyProcs] i = 4 [RunHeavyProcs] waiting all-task [HeavyProc] 5 Start... [Main] Finished. [HeavyProc] 5 Start... [HeavyProc] 5 Start... [HeavyProc] 5 Start... [HeavyProc] 5 Start... [RunHeavyProcs] all-task is completed [RunHeavyProcs] r = 5 -- Passed_HeavyProc [RunHeavyProcs] r = 5 -- Passed_HeavyProc [RunHeavyProcs] r = 5 -- Passed_HeavyProc [RunHeavyProcs] r = 5 -- Passed_HeavyProc [RunHeavyProcs] r = 5 -- Passed_HeavyProc

該当のソースコード

cs

using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /* 非同期処理の練習 https://qiita.com/inew/items/0126270bca99883605de */ namespace SushiTabetai { internal static class Program { // Entry-point static void Main(string[] args) { Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.White; WriteLineColor("[Main] start...", ConsoleColor.Yellow); /* async voidを使うと警告がでる場合があるので, 値の破棄"_"を使うと 回避できるかもしれない. 使用する場合は注意. */ _ = RunHeavyProcs(); WriteLineColor("[Main] Finished.", ConsoleColor.Yellow); Console.ReadKey(); } // 重い処理 static string HeavyProc(int x) //static async Task<string> HeavyProc(int x) { WriteLineColor($"[HeavyProc] {x} Start...", ConsoleColor.DarkGreen); Thread.Sleep(2000); //await Task.Delay(2000); return $"{x} -- Passed_HeavyProc"; } static async Task RunHeavyProcs() { //Console.WriteLine("[RunHeavyProcs] ..."); var taskList = new List<Task<string>>(); for (int i = 0; i < 5; i++) { Console.WriteLine("[RunHeavyProcs] i = {0}", i); var _task = Task.Run(() => HeavyProc(i)); taskList.Add(_task); } Console.WriteLine("[RunHeavyProcs] waiting all-task"); await Task.WhenAll(taskList); Console.WriteLine("[RunHeavyProcs] all-task is completed"); for (int i = 0; i < taskList.Count; i++) { Console.WriteLine("[RunHeavyProcs] r = {0}", taskList[i].Result); } } static void WriteLineColor(string str, ConsoleColor col) { var tmpCol = Console.ForegroundColor; Console.ForegroundColor = col; Console.WriteLine(str); Console.ForegroundColor = tmpCol; } } }

長文失礼しました。上記不明点についてご教示いただけたら幸いです。
よろしくお願いいたします。

環境

Visual Studio Code (最新) + C#プラグイン
.NET SDK 6.0.101
(vscode内ターミナルでdotnetコマンドで実行)

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。