ASP.NET の非同期でありがちな Deadlock を克服する - 松崎 剛 Blog - Site Home - MSDN Blogs blogs.msdn.com/b/tsmatsuz/arc…
2015-04-30 21:58:55@aetos382 @xin9le @chocolamint それって、デフォルトが逆じゃ無いって話ですかね
2015-04-30 22:03:14@takekazuomi @aetos382 @chocolamint あ、サーバー側というのはWebアプリのつもりで書きました。デフォルトを逆にして欲しいと思うことは多々ありますね...。というか、いつもそう思っていますw
2015-04-30 22:05:06@xin9le @takekazuomi @chocolamint なんか ASPNET でも true にしとかないと HttpContext がどうにかなっちゃう(よくわからない)ので、やっぱり基本的にはアプリ/ライブラリで切り分けるのがいいのかなーと思ってます…。
2015-04-30 22:08:44@aetos382 @takekazuomi @chocolamint 確かにHttpContext云々はあるのですが、HttpContextを滅多に使わないのでそういう考えなのかもです。アプリ/ライブラリでの切り分けがダメとは全然思っていません。
2015-04-30 22:10:44@xin9le @takekazuomi @chocolamint ただ、HttpContext どこで使ってるかわからないので…。完全に自分で書いたコードだけ呼んでる場合はいいですけど、他人のコードを呼ぶ時は true かなーと。
2015-04-30 22:13:05@aetos382 @xin9le @chocolamint レスポンスに合わせたい場合と、関係無くF&Fでいい場合と考えるとASP.NETで同期コンテキストが提供されてるのは妥当な気がします。デフォルトで同期コンテキストを見るのも分かるような
2015-04-30 22:17:39ConfigureAwait(false)されてないTaskの完了を待たずにHttpContextが完了しちゃうと死ぬのか。全然別の話だった。失礼。
2015-04-30 22:19:38HttpContext触らなければConfigureAwait(false)してもいいってのは、クライアントアプリでビューとバインドされたビューモデルのプロパティやフォーム/ウィンドウのコントロールを触らなきゃConfigureAwait(false)していいって話とほぼ同義?
2015-04-30 22:21:30非同期が難しいんじゃなくて、ConfigureAwait(true) でないといけない処理の存在が非同期を難しくしてるんやんなぁ。
2015-04-30 22:46:21で、1では HttpContext.Current は not null だけど、2では null になる。3は ConfigureAwait(false) だと null になり得る。ConfigureAwait(true) なら not null。
2015-05-01 01:14:50ConfigureAwait(false) の場合、3(後続処理)は2(ワーカースレッド)と同じスレッドで動くので、HttpContext.Current は null。
2015-05-01 02:01:38ConfigureAwait(true) でも、await する前にワーカースレッドが終わってしまえば、3(後続処理)は1(呼び出し元)と同じスレッドで動く。また、スレッドプールはスレッドを再利用するので、ワーカースレッドが終わっていなくても1と3が同じスレッドになることはある。
2015-05-01 02:02:40HttpContext.Current == null なワーカースレッド内で別の非同期メソッドを ConfigureAwait(true) で呼んだら HttpContext.Current は復旧するのかってのは調べなかったな。復旧しない気がするが。
2015-05-01 03:09:19復旧しないとすれば、中で何をしているかわからない(HttpContext.Current を参照しているかもしれない)ライブラリコードを、ワーカースレッドから呼ぶべきではない、その場合は ConfigureAwait(true) にしておくべき、ということになるか。
2015-05-01 03:11:27確認した。一度 ConfigureAwait(false) にすると、その後続の中では HttpContext.Current はずっと null のまま。途中で ConfigureAwait を書かなかったり true にしても null のまま。
2015-05-01 11:13:59WPFはわからんからWinForms(ひさしぶり!)で確認したけど、こっちでも、一度falseにしたら、その後でtrueにしてもUIスレッドには回ってこなかった。どうも、一度falseにすると、同期コンテキストからデタッチされて、その後は再アタッチされないみたいな感じ?
2015-05-01 11:21:36だったらライブラリコードの中でも、非同期メソッドの最初に一度だけ ConfigureAwait(false) しておけば、後はしなくていいんじゃない? まぁ、Awaiter だか SynchronizationContext だかの実装次第ってのはあるのかもしれんけど。
2015-05-01 11:23:33あと、一度 false にしてから後で true にすると、同期コンテキストは拾わないけどスレッドは切り替わる可能性がある。そういう意味ではパフォーマンス的な影響はあるのかもしれない。ずっと false なら、ずっと同じワーカースレッドで処理が走る。
2015-05-01 11:26:25なるほど、ConfigureAwait(false) にするってことは、SynchronizationContext.Current も null になるってことか。一度 null になると、後で true にしても戻らないのは、HttpContext と同じ。
2015-05-01 11:28:24まず前提として、ワーカースレッドは同期コンテキストを持たない。WPF や WinForms なら UI スレッド、ASPNET ならリクエストスレッドのみが同期コンテキストを持つ。
2015-05-01 11:34:42非同期メソッドの中で走る非同期処理(ややこしい)はワーカースレッドで実行される。ので、同期コンテキストを持たない。ConfigureAwait(false) は、スレッドスイッチを抑制する。ので、同期コンテキストを拾わない。
2015-05-01 11:36:03