ConfigureAwait

ConfigureAwait関連の会話
3
あえとす @aetos382

ASP.NET の非同期でありがちな Deadlock を克服する - 松崎 剛 Blog - Site Home - MSDN Blogs blogs.msdn.com/b/tsmatsuz/arc…

2015-04-30 21:58:55
Takekazu Omi @takekazuomi

@aetos382 @xin9le @chocolamint それって、デフォルトが逆じゃ無いって話ですかね

2015-04-30 22:03:14
じんぐる (Takaaki Suzuki) @xin9le

@takekazuomi @aetos382 @chocolamint あ、サーバー側というのはWebアプリのつもりで書きました。デフォルトを逆にして欲しいと思うことは多々ありますね...。というか、いつもそう思っていますw

2015-04-30 22:05:06
あえとす @aetos382

@xin9le @takekazuomi @chocolamint なんか ASPNET でも true にしとかないと HttpContext がどうにかなっちゃう(よくわからない)ので、やっぱり基本的にはアプリ/ライブラリで切り分けるのがいいのかなーと思ってます…。

2015-04-30 22:08:44
じんぐる (Takaaki Suzuki) @xin9le

@aetos382 @takekazuomi @chocolamint 確かにHttpContext云々はあるのですが、HttpContextを滅多に使わないのでそういう考えなのかもです。アプリ/ライブラリでの切り分けがダメとは全然思っていません。

2015-04-30 22:10:44
あえとす @aetos382

@xin9le @takekazuomi @chocolamint ただ、HttpContext どこで使ってるかわからないので…。完全に自分で書いたコードだけ呼んでる場合はいいですけど、他人のコードを呼ぶ時は true かなーと。

2015-04-30 22:13:05
Takekazu Omi @takekazuomi

@aetos382 @xin9le @chocolamint レスポンスに合わせたい場合と、関係無くF&Fでいい場合と考えるとASP.NETで同期コンテキストが提供されてるのは妥当な気がします。デフォルトで同期コンテキストを見るのも分かるような

2015-04-30 22:17:39
しゃるしぃ @chocolamint

ConfigureAwait(false)されてないTaskの完了を待たずにHttpContextが完了しちゃうと死ぬのか。全然別の話だった。失礼。

2015-04-30 22:19:38
しゃるしぃ @chocolamint

HttpContext触らなければConfigureAwait(false)してもいいってのは、クライアントアプリでビューとバインドされたビューモデルのプロパティやフォーム/ウィンドウのコントロールを触らなきゃConfigureAwait(false)していいって話とほぼ同義?

2015-04-30 22:21:30
Takekazu Omi @takekazuomi

同期コンテキスト自体がかなり高レベルな概念なので、デフォルトは無視で良かったのではないか

2015-04-30 22:22:27
あえとす @aetos382

非同期が難しいんじゃなくて、ConfigureAwait(true) でないといけない処理の存在が非同期を難しくしてるんやんなぁ。

2015-04-30 22:46:21
あえとす @aetos382

で、1では HttpContext.Current は not null だけど、2では null になる。3は ConfigureAwait(false) だと null になり得る。ConfigureAwait(true) なら not null。

2015-05-01 01:14:50
あえとす @aetos382

ConfigureAwait(false) の場合、3(後続処理)は2(ワーカースレッド)と同じスレッドで動くので、HttpContext.Current は null。

2015-05-01 02:01:38
あえとす @aetos382

ConfigureAwait(true) でも、await する前にワーカースレッドが終わってしまえば、3(後続処理)は1(呼び出し元)と同じスレッドで動く。また、スレッドプールはスレッドを再利用するので、ワーカースレッドが終わっていなくても1と3が同じスレッドになることはある。

2015-05-01 02:02:40
あえとす @aetos382

HttpContext.Current == null なワーカースレッド内で別の非同期メソッドを ConfigureAwait(true) で呼んだら HttpContext.Current は復旧するのかってのは調べなかったな。復旧しない気がするが。

2015-05-01 03:09:19
あえとす @aetos382

復旧しないとすれば、中で何をしているかわからない(HttpContext.Current を参照しているかもしれない)ライブラリコードを、ワーカースレッドから呼ぶべきではない、その場合は ConfigureAwait(true) にしておくべき、ということになるか。

2015-05-01 03:11:27
あえとす @aetos382

確認した。一度 ConfigureAwait(false) にすると、その後続の中では HttpContext.Current はずっと null のまま。途中で ConfigureAwait を書かなかったり true にしても null のまま。

2015-05-01 11:13:59
あえとす @aetos382

WPFはわからんからWinForms(ひさしぶり!)で確認したけど、こっちでも、一度falseにしたら、その後でtrueにしてもUIスレッドには回ってこなかった。どうも、一度falseにすると、同期コンテキストからデタッチされて、その後は再アタッチされないみたいな感じ?

2015-05-01 11:21:36
あえとす @aetos382

だったらライブラリコードの中でも、非同期メソッドの最初に一度だけ ConfigureAwait(false) しておけば、後はしなくていいんじゃない? まぁ、Awaiter だか SynchronizationContext だかの実装次第ってのはあるのかもしれんけど。

2015-05-01 11:23:33
あえとす @aetos382

あと、一度 false にしてから後で true にすると、同期コンテキストは拾わないけどスレッドは切り替わる可能性がある。そういう意味ではパフォーマンス的な影響はあるのかもしれない。ずっと false なら、ずっと同じワーカースレッドで処理が走る。

2015-05-01 11:26:25
あえとす @aetos382

なるほど、ConfigureAwait(false) にするってことは、SynchronizationContext.Current も null になるってことか。一度 null になると、後で true にしても戻らないのは、HttpContext と同じ。

2015-05-01 11:28:24
あえとす @aetos382

まず前提として、ワーカースレッドは同期コンテキストを持たない。WPF や WinForms なら UI スレッド、ASPNET ならリクエストスレッドのみが同期コンテキストを持つ。

2015-05-01 11:34:42
あえとす @aetos382

非同期メソッドの中で走る非同期処理(ややこしい)はワーカースレッドで実行される。ので、同期コンテキストを持たない。ConfigureAwait(false) は、スレッドスイッチを抑制する。ので、同期コンテキストを拾わない。

2015-05-01 11:36:03