問題タブ [synchronizationcontext]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - 彼らのSynchronizationContextの比較
同期コンテキストを比較するにはどうすればよいですか?BeginInvokeを使用すると、同じディスパッチャが異なるSynchronizationContextを作成できるようです。2つの(等しくない)コンテキストにドリルダウンすると、ディスパッチャーのスレッドIDは同じですが、互いに等しくないことがわかります。
たぶん、それらの2つを一緒に使用することはできません。私はこれが実際に機能することに気づきました:
更新しかし、奇妙なことに、それは常に機能するとは限りません。
たとえば、一致する_contextを取得することはなく、永久に継続します。すべきではありませんが。この後者の例では、スレッドは実際には同じになり、コンテキストがありますが、それは異なります。
Update2わかりました、動作しましたが、本当に不快に感じます。どうやら、投稿または送信するとき、タスクは正しいスレッドから実行されますが、UIから来ていない場合は、新しいSynchronizationContextが生成されているようです。
そしてこれを見てください:
「直接の発信者には完全な信頼が必要です。このメンバーは、部分的に信頼されているコードや透過的なコードでは使用できません。」:(
c# - 特定のスケジューラ (例: GUI) でタスクを開始するにはどうすればよいですか?
Task
TPL でを作成しようとしています。例えば:
これは問題なく動作しますが、今は GUI スレッドで開始したいと考えています。
次のようにして、GUI スケジューラーをキャッシュできます。
しかし、このスケジューラを使用して新しいタスクを開始する方法がわかりません。私が見つけることができるすべての例は、最初のタスクが終了したら を使用Task.ContinueWith()
して 2 番目のタスクをスケジュールするために使用し_uiScheduler
ますが、このスケジューラを使用して最初のタスクを作成したいと考えています。
乾杯
asp.net - sync-on-async の TaskScheduler と SynchronizationContext で混乱し、同期コンテキストを制御できませんか?
問題
シンプルな web-service を含む ASP.NET 4.0 WebForms ページがありますWebMethod
。このメソッドは、非同期/TPL コードへの同期ラッパーとして機能します。私が直面している問題は、内部Task
に null SynchronizationContext
(私の好み) がある場合があることですが、同期コンテキストがSystem.Web.LegacyAspNetSynchronizationContext
. 私が提供した例では、これは実際には問題を引き起こしませんが、実際の開発シナリオではデッドロックにつながる可能性があります。
サービスへの最初の呼び出しは常に null 同期コンテキストで実行されるように見えますが、次のいくつかもそうなる可能性があります。しかし、いくつかの急速な要求が発生すると、ASP.NET 同期コンテキストにポップし始めます。
コード
存在の定義TaskHolder
:
分析
私の理解でTaskScheduler.Default
は、それはThreadPool
スケジューラです。つまり、スレッドは ASP.NET スレッドに到達しません。この記事によると、「タスク並列ライブラリと PLINQ の既定のスケジューラは、.NET Framework ThreadPool を使用して作業をキューに入れ、実行します」。それに基づいて、SynchronizationContext
内部SampleTask
は常にnullになると思います。
さらに、私の理解ではSampleTask
、 ASP.NET 上にある場合、 inSynchronizationContext
への呼び出しがデッドロックする可能性があります。.Result
MyWebMethod
「完全に非同期」にするつもりはないので、これは「同期オン非同期」シナリオです。Stephen Toub によるこの記事によると、「「非同期ではなく同期」が本当に必要な場合はどうすればよいでしょうか? というタイトルのセクションにあります。次のコードは安全なラッパーである必要があります。
同じく Stephen Toub によるこの別の記事によると、上記は機能的に次のものと同等である必要があります。
.NET 4.0 を使用しているため、.NET にアクセスできません。これは私の問題だと思いましTaskCreationOptions.DenyChildAttach
た。しかし、同じサンプルを .NET 4.5 で実行して切り替えたところTaskCreationOptions.DenyChildAttach
、同じように動作しました (ASP.NET 同期コンテキストを取得する場合があります)。
そこで、「元の」推奨事項に近づき、.NET 4.5 で実装することにしました。
そして、これは常に null 同期コンテキストを持つという点で機能します。Task.Run と Task.Factory.StartNew の記事が間違っていることを示唆しているのはどれですか?
実用的なアプローチは、.NET 4.5 にアップグレードしてTask.Run
実装を使用することですが、それには開発時間が必要になるため、(可能であれば) もっと差し迫った問題に費やしたいと思います。さらにTaskScheduler
、さまざまなシナリオで何が起こっているのかを把握したいと思いTaskCreationOptions
ます。
.NET 4.0 では、思い通りに動作しているように見えることを偶然発見しましたTaskCreationOptions.PreferFairness
(すべての実行で同期コンテキストが null になっています)。シナリオ)。
編集
いくつかの追加情報...デッドロックを行うコードでサンプルコードを更新し、タスクが実行されているスレッドを示すデバッグ出力を含めました。プレタスクまたは継続タスクの出力が WebMethod と同じスレッド ID を示している場合、デッドロックが発生します。
不思議なことに、ProgressMessageHandler を使用しないと、デッドロックを再現できないようです。私の印象では、これは問題ではなく、下流のコードに関係なく、適切なメソッドTask.Factory.StartNew
またはTask.Run
メソッドを使用して非同期メソッドを同期コンテキストに安全に「ラップ」できるはずだというものでした。しかし、これはそうではないようです?
c# - Task.ContinueWith(..., TaskScheduler.FromCurrentSynchronizationContext()) が UI スレッドで実行されないシナリオはありますか?
次のような奇妙なコードを観察しています。
そこで 2 番目のタスクがイベントを呼び出し、それが次に GUI を更新しようとすると、恐ろしいクロススレッド例外が発生します。
Thread.CurrentThread.ManagedThreadId
2 番目のタスクのメソッドを確認すると、実際には UI スレッドで実行されていないことがわかります。
タスクを生成したコードは、UI スレッドで実行されています。
これがうまくいかないシナリオはありますか?
c# - メインスレッドが終了すると、SynchronizationContext はどうなりますか?
メインスレッドと、何らかの作業を行うために作成した別のスレッドの 2 つのスレッドがあります。メイン スレッドが既に終了しているときに、いくつかの UI 要素が更新されている他のスレッドから originalContext.Post (メイン スレッドの SyncronizationContext) を呼び出すとどうなるかわかりません。これは安全ですか?なぜですか?
前もって感謝します。
winforms - System.Windows.Forms.Form インスタンスが存在する場合、await Task.Delay(...) がフリーズします
DoTheStuff().Wait();
コンソール アプリケーションとして実行している場合、次のプログラムがハングします。
ただし、行をコメントアウトすると、期待どおりに機能しますnew Form();
。(1 秒間実行してから終了します)。
期待される動作を維持しながら Form インスタンスを保持するにはどうすればよいですか?
さて、興味があれば背景をいくつか:
Windows サービスとして (ローカルでテストするときはコンソールとして) ホストされているアプリケーションがあります。
SystemEvents.TimeChanged
イベントにアクセスできる必要があります。
ただし、ドキュメントに従って、これは Windows フォームがある場合にのみ機能します (したがって、サービスまたはコンソール アプリでは機能しません)。回避策は、リンクされたドキュメントに記載されており、非表示のフォームを作成することで構成されています。
残念ながら、プログラムは代わりに完全にフリーズします。これは、await とForm
インスタンスを持つことの組み合わせが原因です。
SystemEvents.TimeChanged
では、イベントにアクセスしている間、どうすれば予想される非同期/待機動作を維持できますか?
以下のヘルプのおかげで、フリーズせずに動作する修正されたコードがここにあります。
私のプログラムでは、待機中のタスクにスレッドプールを使用する必要があるため、「SynchronizationContext.SetSynchronizationContext(null);」を使用する必要があります。フォームは明らかに何らかの理由で初期化したため、これは良い習慣ではないと思います。しかし、ユーザー入力なしで非表示のフォームを実行すると (これはサービスです!)、今のところ害は見られません。
MS は例 2 を使用して発生する可能性のある問題についても言及していないため、ドキュメントは少し不完全に感じられます (await/async は、フォームのインスタンス化時に動作を暗黙的に変更します)。
c# - 本の「現在の SynchronizationContext は現在のスレッドのプロパティです」というフレーズは正しいですか?
「現在のSynchronizationContextは現在のスレッドのプロパティです」というフレーズを読んだので、少し混乱しています...
VS2010 の C# アプリ コードで入力すると、Thread.CurrentThread.
Intellisense によって提供される選択肢のドロップダウン リストに、スレッドのコンテキスト関連のプロパティが見つかりません。
現在の同期コンテキストは " " を介して取得できることを知っています= SynchronizationContext.Current;
。しかし、これは、並列スレッドやタスクなどで同時に実行される場合には、あまり幸運ではありません。
コンソールまたは WPF (*)アプリから、独自のメイン UI スレッドと TPL タスクでいくつかの Windows フォームを作成して起動するとします。
各 winform には独自のWindowsFormaSynchronizationContextが必要であり、WPF には独自のDispatcherSynchronizationContext ( SynchronizationContext クラスのサブクラス) インスタンスが必要であり、タスクは独自の同期コンテキストを持つThreadPoolで実行され、 LongRunning タスクはそのスレッド プールから実行される可能性があります。独自の同期コンテキスト...
では、なぜSynchronizationContext
スレッドから定義できないのでしょうか? 「特定のスレッドから SynchronizationContext を取得する」という質問に対するすべての回答は、この可能性を否定する点で全会一致のようです...
最後になりましたが、「現在の SynchronizationContext は現在のスレッドのプロパティです」
というフレーズは正しいですか?
次に、さまざまな特定のスレッド インスタンスに対してこのプロパティの値を取得するにはどうすればよいですか?
(*)
最近、本質的に winform を使用する C# WPF アプリ コードが提供されました。