回答編集履歴

2

追記

2020/09/19 07:40

投稿

退会済みユーザー
test CHANGED
@@ -34,11 +34,15 @@
34
34
 
35
35
 
36
36
 
37
- 前者の async / await を使った方は await で fuga の処理が終わるのを待ちますがメッセージループは処理されるので GUI はフリーズしないという、たぶん質問者さんが期待する動きになると思いますが、後者はデッドロックになると思います
37
+ 前者の async / await を使った方は await で fuga の処理が終わるのを待ちますがメッセージループは処理されるので GUI はフリーズしません。それはたぶん質問者さんが期待する動きになると思います。
38
+
39
+
40
+
38
-
41
+ しかし、質問者さんのコードの後者の Task.Result を使った方はデッドロックになると思います。
39
-
40
-
42
+
43
+
44
+
41
- 「思います」と言うだけではなので、Windows Forms アプリで以下のコードを書いて検証してみましたが、コメントにデッドロックと書いた方(質問者さんの例では後者の方)はデッドロックになります。
45
+ 「思います」と言うだけでは説得力がので、Windows Forms アプリで以下のコードを書いて検証してみましたコメントにデッドロックと書いた方(質問者さんの例では後者の方)はデッドロックになります。
42
46
 
43
47
 
44
48
 
@@ -72,6 +76,12 @@
72
76
 
73
77
  // デッドロック
74
78
 
79
+ // Task.Result プロパティの get アクセサーにアクセスすると
80
+
81
+ // 非同期操作が完了するまで呼び出し元のスレッドがブロックされる。
82
+
83
+ // これは、Wait メソッドを呼び出すことと同じ
84
+
75
85
  private void button1_Click(object sender, EventArgs e)
76
86
 
77
87
  {

1

訂正

2020/09/19 07:40

投稿

退会済みユーザー
test CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  ```
18
18
 
19
- static async Task<string> fuga()
19
+ private async Task<string> fuga()
20
20
 
21
21
  {
22
22
 
@@ -102,13 +102,109 @@
102
102
 
103
103
 
104
104
 
105
+ private async Task<string> TimeCosumingMethod()
106
+
107
+ {
108
+
109
+ await Task.Delay(3000);
110
+
111
+ return "TimeCosumingMethod の戻り値";
112
+
113
+ }
114
+
115
+ }
116
+
117
+ }
118
+
119
+ ```
120
+
121
+
122
+
123
+ その理由については以下の記事の「図 3 非同期コードをブロックする際によくあるデッドロックの問題」のセクションが参考になると思います。
124
+
125
+
126
+
127
+ 非同期プログラミングのベスト プラクティス
128
+
129
+ [https://docs.microsoft.com/ja-jp/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming](https://docs.microsoft.com/ja-jp/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming)
130
+
131
+
132
+
133
+ ちなみに、上の記事に書いてある通り、コンソールアプリであればデッドロックにはなりません。以下のコードで確認しました。
134
+
135
+
136
+
137
+ ```
138
+
139
+ using System;
140
+
141
+ using System.Threading.Tasks;
142
+
143
+ using System.Threading;
144
+
145
+
146
+
147
+ namespace ConsoleAppAsync3
148
+
149
+ {
150
+
151
+ class Program
152
+
153
+ {
154
+
155
+ static async Task Main(string[] args)
156
+
157
+ {
158
+
159
+ Console.WriteLine("Main のはじまり " +
160
+
161
+ Thread.CurrentThread.ManagedThreadId);
162
+
163
+
164
+
165
+ string str1 = await TimeCosumingMethod();
166
+
167
+ Console.WriteLine(str1);
168
+
169
+
170
+
171
+ string str2 = TimeCosumingMethod().Result;
172
+
173
+ Console.WriteLine(str2);
174
+
175
+
176
+
177
+ Console.WriteLine("Main のおわり " +
178
+
179
+ Thread.CurrentThread.ManagedThreadId);
180
+
181
+ }
182
+
183
+
184
+
105
185
  static async Task<string> TimeCosumingMethod()
106
186
 
107
- {
187
+ {
188
+
189
+ Console.WriteLine("TimeCosumingMethod はじまり " +
190
+
191
+ Thread.CurrentThread.ManagedThreadId);
192
+
193
+
108
194
 
109
195
  await Task.Delay(3000);
110
196
 
197
+
198
+
199
+ Console.WriteLine("TimeCosumingMethod おわり " +
200
+
201
+ Thread.CurrentThread.ManagedThreadId);
202
+
203
+
204
+
111
- return "TimeCosumingMethod の戻り値";
205
+ return "TimeCosumingMethod の戻り値 " +
206
+
207
+ Thread.CurrentThread.ManagedThreadId;
112
208
 
113
209
  }
114
210
 
@@ -120,102 +216,6 @@
120
216
 
121
217
 
122
218
 
123
- その理由については以下の記事の「図 3 非同期コードをブロックする際によくあるデッドロックの問題」のセクションが参考になると思います。
124
-
125
-
126
-
127
- 非同期プログラミングのベスト プラクティス
128
-
129
- [https://docs.microsoft.com/ja-jp/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming](https://docs.microsoft.com/ja-jp/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming)
130
-
131
-
132
-
133
- ちなみに、上の記事に書いてある通り、コンソールアプリであればデッドロックにはなりません。以下のコードで確認しました。
134
-
135
-
136
-
137
- ```
138
-
139
- using System;
140
-
141
- using System.Threading.Tasks;
142
-
143
- using System.Threading;
144
-
145
-
146
-
147
- namespace ConsoleAppAsync3
148
-
149
- {
150
-
151
- class Program
152
-
153
- {
154
-
155
- static async Task Main(string[] args)
156
-
157
- {
158
-
159
- Console.WriteLine("Main のはじまり " +
160
-
161
- Thread.CurrentThread.ManagedThreadId);
162
-
163
-
164
-
165
- string str1 = await TimeCosumingMethod();
166
-
167
- Console.WriteLine(str1);
168
-
169
-
170
-
171
- string str2 = TimeCosumingMethod().Result;
172
-
173
- Console.WriteLine(str2);
174
-
175
-
176
-
177
- Console.WriteLine("Main のおわり " +
178
-
179
- Thread.CurrentThread.ManagedThreadId);
180
-
181
- }
182
-
183
-
184
-
185
- static async Task<string> TimeCosumingMethod()
186
-
187
- {
188
-
189
- Console.WriteLine("TimeCosumingMethod はじまり " +
190
-
191
- Thread.CurrentThread.ManagedThreadId);
192
-
193
-
194
-
195
- await Task.Delay(3000);
196
-
197
-
198
-
199
- Console.WriteLine("TimeCosumingMethod おわり " +
200
-
201
- Thread.CurrentThread.ManagedThreadId);
202
-
203
-
204
-
205
- return "TimeCosumingMethod の戻り値 " +
206
-
207
- Thread.CurrentThread.ManagedThreadId;
208
-
209
- }
210
-
211
- }
212
-
213
- }
214
-
215
- ```
216
-
217
-
218
-
219
219
  結果は:
220
220
 
221
221