提示コードですが buttonConvert_Click
関数の内部ですがthis.Invokeにコードが推移しませんこれはなぜでしょうか?
参考サイト:https://www.codeproject.com/Questions/66345/Invoking-not-working
cs
1 2 private void Process(SemaphoreSlim slim,string path,string ext) 3 { 4 slim.Wait(); 5 string file = Path.ChangeExtension(path, ext); 6 ImageMagick.MagickImage img = new ImageMagick.MagickImage(path); 7 img.Write(file); 8 9 img.Dispose(); 10 11 12 slim.Release(); 13 14 } 15 16 List<Task> taskList = new List<Task>(); 17 18 private void buttonConvert_Click(object sender, EventArgs e) 19 { 20 21 Stopwatch sw = new Stopwatch(); 22 sw.Start(); 23 var slim = new SemaphoreSlim(3); 24 25 foreach (string path in filePathList) 26 { 27 taskList.Add(Task.Factory.StartNew(() => 28 { 29 Process(slim, path,".jpeg"); 30 Debug.WriteLine("ああああ"); 31 this.Invoke((Action)(() => 32 { 33 progressBar_float += progressBarPerFile; 34 progressBar.Value = (int)progressBar_float; 35 Debug.WriteLine("いいい"); 36 37 })); 38 39 Debug.WriteLine("aaaaaaaaaaaaaaa" + progressBar.Value); 40 41 42 })); 43 } 44 45 Task.WhenAll(taskList).Wait(); 46 slim.Dispose(); 47 progressBar.Value = 0; 48 sw.Stop(); 49 TimeSpan ts = sw.Elapsed; 50 Debug.WriteLine(ts.TotalSeconds +"."+ ts.Milliseconds); 51 52 53 54 55 } 56
コンソールログ
'HEIC_Converter.exe' (CoreCLR: clrhost): 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.7\System.Runtime.InteropServices.RuntimeInformation.dll' が読み込まれました。シンボルの読み込みをスキップしました。モジュールは最適化されていて、デバッグ オプションの [マイ コードのみ] 設定が有効になっています。 ああああ ああああ ああああ ああああ ああああ ああああ ああああ ああああ ああああ ああああ ああああ ああああ ああああ ああああ ああああ スレッド 0x1b14 はコード 0 (0x0) で終了しました。 ああああ ああああ ああああ ああああ ああああ プログラム '[9508] HEIC_Converter.exe' はコード 4294967295 (0xffffffff) で終了しました。
こちらの質問が複数のユーザーから「調査したこと・試したことが記載されていない質問」という指摘を受けました。
Task.WhenAll(taskList).Wait(); でメッセージループをブロックしているので Invoke が進みません。
別スレッドで待機するなり、非同期メソッドにするなりしてください。
KOZ6.0さんの回答がまさに的を得た回答だと思います。
ただ、質問者さんは理解できていないような気がするのでちょっとだけ解説付けます。
①UIスレッド
buttonConvert_Clickは、名称からボタンの処理だと思うので、
これはUIスレッドで動作します。
その後、Task.WhenAll(taskList).Wait();にて別スレッドの終了を待ちます。
このとき、UIスレッドでの処理は終了していない状態になっています。
②別スレッド
Task.Factory.StartNewにて別スレッドを起動しています。
この別スレッド内からthis.Invokeを実行することで
UIスレッドが空くまで待機しています。
このとき、別スレッドはの処理は終了していない状態になっています。
①は②の終了を待ち、②は①の終了を待つことになっているため、
いわゆるデットロックの状態になっています。
Task.WhenAll(taskList).Wait();は同期的に待機します。
つまり、UIスレッドが終了していない状態。
await Task.WhenAll(taskList);は非同期的に待機します。
内部的にここから再開することを覚えておいて、一旦UIスレッドを終了します。
別スレッドの終了を検知したら、再開ポイントに戻って
再びUIスレッドの続きの処理を続行します。
Wait()使うなと良く掲示板などで書かれていますが
まさにその状態ですね。

なるほど[この別スレッド内からthis.Invokeを実行することで
UIスレッドが空くまで待機しています。]
という説明文ですがこれはthis.InvokeでUIスレッドが空くまで待機してから処理するという意味なのでしょうか?
そうです。
回答1件
あなたの回答
tips
プレビュー