Visual Studio 2015 (C#6.0)
.NET Framework 4.6
WPF で開発をする上で非同期処理について調査していたところ、
次のような不可解な現象に遭遇したので助けてください。
ご存じの通り、
WPF は起動直後に App クラスがインスタンス化されて、
裏側で Run されると OnStartup() メソッドが呼ばれます。
その処理の途中で非同期処理をおこなうテストコードを入れてみました。
C#
1namespace WpfApplication1 2{ 3 using System.Threading.Tasks; 4 using System.Windows; 5 6 /// <summary> 7 /// App.xaml の相互作用ロジック 8 /// </summary> 9 public partial class App : Application 10 { 11 public App() 12 { 13 System.Diagnostics.Debug.WriteLine("App() ------------------------------------------"); 14 Test(); 15 } 16 17 protected override void OnStartup(StartupEventArgs e) 18 { 19 base.OnStartup(e); 20 21 System.Diagnostics.Debug.WriteLine("OnStartup() ------------------------------------"); 22 Test(); 23 } 24 25 private void Test() 26 { 27 var hoge = Hoge(); 28 System.Diagnostics.Debug.WriteLine("Hoge() を待つよ。"); 29 hoge.Wait(); 30 System.Diagnostics.Debug.WriteLine("Hoge() が終わったよ。"); 31 32 var hogeAsync = HogeAsync(); 33 System.Diagnostics.Debug.WriteLine("HogeAsync() を待つよ。"); 34 hogeAsync.Wait(); 35 System.Diagnostics.Debug.WriteLine("HogeAsync() が終わったよ。"); 36 } 37 38 private Task Hoge() 39 { 40 System.Diagnostics.Debug.WriteLine("Hoge() が呼び出されたよ。"); 41 return Task.Run(() => DoWork()); 42 } 43 44 private async Task HogeAsync() 45 { 46 System.Diagnostics.Debug.WriteLine("HogeAsync() が呼び出されたよ。"); 47 await Task.Run(() => DoWork()); 48 } 49 50 private void DoWork() 51 { 52 System.Diagnostics.Debug.WriteLine("お仕事したよ。"); 53 } 54 } 55}
出力結果は以下の通りになりました。
text
1App() ------------------------------------------ 2Hoge() が呼び出されたよ。 3Hoge() を待つよ。 4お仕事したよ。 5Hoge() が終わったよ。 6HogeAsync() が呼び出されたよ。 7お仕事したよ。 8HogeAsync() を待つよ。 9HogeAsync() が終わったよ。 10OnStartup() ------------------------------------ 11Hoge() が呼び出されたよ。 12Hoge() を待つよ。 13お仕事したよ。 14Hoge() が終わったよ。 15HogeAsync() が呼び出されたよ。 16お仕事したよ。 17HogeAsync() を待つよ。
最後は HogeAsync() のタスクから戻って来れずに、
「HogeAsync() が終わったよ。」のメッセージも出力されず、
アプリケーションがフリーズしてしまいました。
「Task.Wait() するとデッドロックする」と良く聞くので、
これもそのひとつなのかな、と思いますが確証がありません。
そこで疑問が 2 点あります。
Q1. なぜフリーズしてしまうのか
App() コンストラクタ内ではフリーズしないのに、
なぜ OnStartup() メソッド内ではフリーズしてしまうのでしょうか。
Q2. Hoge() と HogeAsync() の違い
Hoge() によるタスクでは完了後に戻って来れるのに、
なぜ HogeAsync() によるタスクでは完了後に戻って来れないのでしょうか。
回答1件
あなたの回答
tips
プレビュー