teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

文章のへんなところを修正

2017/06/23 15:37

投稿

tamoto
tamoto

スコア4346

answer CHANGED
@@ -5,9 +5,9 @@
5
5
  厳密に言うと、「`SynchronizationContext`という、プログラムの実行コンテキストを同期するためのstaticなプロパティに中身が存在する場合にデッドロックが発生する可能性がある」のですが、コンソールアプリケーションだとこれがデフォルトでは`null`になっています。そうすると、awaitした後に特定のコンテキストに復帰する動作が行われなくなるため、根本的にデッドロックが発生する原因が失われます。つまり、コンソールアプリケーションである限り、たとえ`Wait`メソッドを使ってもスレッド同期によるデッドロックが発生しないということです。
6
6
 
7
7
  しかし!!`System.Windows.Forms.Form`のインスタンスを生成するとき、どうやらコンストラクタがSynchronizationContextを生成するようです。つまり、質問の`PrivateAccess`クラスが`Form`を継承しているかどうかで、SynchronizationContextの有無が異なっていることになります。
8
- すると、`Main`メソッド内で呼び出している`Wait`と`privateasynctest`メソッドのawaitがぶつかってデッドロックを引き起こしています。
8
+ すると、`Main`メソッド内で呼び出している`Wait`と`privateasynctest`メソッドのawaitがぶつかってデッドロックを引き起こすようになるわけです
9
9
 
10
- これは……ちょっと想定外のクソ挙動で戸惑っていますが、、awaitを呼び出している式に対してそれぞれ`ConfigureAwait(false)`を付けることでSynchronizationContextの伝播を断ち切ることが出来るので、async/awaitを使う際はこちらを徹底することでデッドロックを回避することができます。
10
+ これは……ちょっと想定外のクソ挙動で戸惑っていますが、、とりあえず、awaitを呼び出している式に対してそれぞれ`ConfigureAwait(false)`を付けることでSynchronizationContextの伝播を断ち切ることができるので、async/awaitを使う際はこのコーディングを徹底することでデッドロックを完全に回避することができます。
11
11
 
12
12
  以下に、最低限の書き換えで動作するようにしたコードを掲載します。こちらをコピペで試してみてください。
13
13
  ```csharp
@@ -51,7 +51,7 @@
51
51
 
52
52
  そして、元々の質問にあった、「IntelliTestから実行したときデッドロックする」については、こちらは推測ですが、おそらく内部で`Wait`かそれに類する動作を行っていると考えられます。
53
53
  こちらも同期コンテキストの破棄を徹底することで問題は発生しなくなると予想できますが……(もしかして、UI関係とかのコンテキストが重要な非同期メソッドはIntelliTestでは評価できないってことかしら……?)
54
- ついてはさらなる調査が必要なのですが、なんだか根の深い問題な気がします。
54
+ こを掘り下げるにはさらなる調査が必要ですが、なんだか根の深い問題な気がします。
55
55
 
56
56
  ---
57
57