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

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

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

Q&A

解決済

1回答

1826閲覧

C# this.Invoke((Action)(() =>が動作しない原因が知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

0グッド

0クリップ

投稿2022/07/28 10:27

提示コードですが 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) で終了しました。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KOZ6.0

2022/07/28 23:48 編集

Task.WhenAll(taskList).Wait(); でメッセージループをブロックしているので Invoke が進みません。 別スレッドで待機するなり、非同期メソッドにするなりしてください。
kikukiku

2022/07/28 23:40

KOZ6.0さんの回答がまさに的を得た回答だと思います。 ただ、質問者さんは理解できていないような気がするのでちょっとだけ解説付けます。 ①UIスレッド  buttonConvert_Clickは、名称からボタンの処理だと思うので、  これはUIスレッドで動作します。  その後、Task.WhenAll(taskList).Wait();にて別スレッドの終了を待ちます。  このとき、UIスレッドでの処理は終了していない状態になっています。 ②別スレッド  Task.Factory.StartNewにて別スレッドを起動しています。  この別スレッド内からthis.Invokeを実行することで  UIスレッドが空くまで待機しています。  このとき、別スレッドはの処理は終了していない状態になっています。 ①は②の終了を待ち、②は①の終了を待つことになっているため、 いわゆるデットロックの状態になっています。
kikukiku

2022/07/28 23:56

Task.WhenAll(taskList).Wait();は同期的に待機します。 つまり、UIスレッドが終了していない状態。 await Task.WhenAll(taskList);は非同期的に待機します。 内部的にここから再開することを覚えておいて、一旦UIスレッドを終了します。 別スレッドの終了を検知したら、再開ポイントに戻って 再びUIスレッドの続きの処理を続行します。
kikukiku

2022/07/28 23:59

Wait()使うなと良く掲示板などで書かれていますが まさにその状態ですね。
退会済みユーザー

退会済みユーザー

2022/07/29 04:15

なるほど[この別スレッド内からthis.Invokeを実行することで  UIスレッドが空くまで待機しています。] という説明文ですがこれはthis.InvokeでUIスレッドが空くまで待機してから処理するという意味なのでしょうか?
guest

回答1

0

ベストアンサー

質問編集欄より

原因

[
Task.Factory.StartNewにて別スレッドを起動しています。
この別スレッド内からthis.Invokeを実行することで
UIスレッドが空くまで待機しています。
このとき、別スレッドはの処理は終了していない状態になっています。
①は②の終了を待ち、②は①の終了を待つことになっているため、
いわゆるデットロックの状態になっています。

]

解決方法

以下のようにすることで解決しました。

cs

1await Task.WhenAll(taskList);

投稿2022/07/28 23:48

編集2022/07/29 00:06
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問