問題タブ [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.Post が BackgroundWorker 内で機能しない
バックグラウンドワーカーを使用してすべての処理を行っています。その中には、「ログ」テキスト ボックスに書き込む場所がたくさんあります。これらはすべてうまく機能しますが、background-worker の最後、最後の行で、もう 1 つの呼び出しSynchronizationContext
が発生しません。最後の呼び出しではなく、他のすべての呼び出しが機能するのはなぜですか?
アプリケーションが「ハング」するだけで、次のような EventLog エントリさえあることを付け加えておきます。
メソッドは次のとおりDoWork
です ( の呼び出し時に実行されRunWorkerAsync
ます)。
foreach
ループの最後でFinished the compare...
、次の同期呼び出しが実行されます。
実行されることはありません。その方法は次のとおりです。
c# - C#で別のクラスからスレッドメソッドをインスタンス化する
誰かが次の問題に対処する方法を教えてもらえますか? 基本的に、http: //www.codeproject.com/KB/threads/SynchronizationContext.aspxにある次の例のコードを再利用しようとしています 。 理解できない唯一の問題は、RUN メソッドが見つかった場合にインスタンス化する方法です。別のクラス。次のコードを参照してください。
編集:
たとえば、実行メソッドは他の人 (別の開発者) から与えられ、UI スレッド (メイン スレッドまたはクラス Form1) で別のスレッドとしてこのメソッドを実行する必要がありますが、スレッド (実行メソッド) を実行するたびにmListBox
UpdateUI メソッドを使用してListBox を更新する必要もあります。
c# - クロススレッドの相互作用c#
SynchronizationContext
誰かが私のクラス内でThread.join()メソッドを設定する方法、またはクラスとthread.join
メソッドを処理するためのきちんとした方法があるかどうかを教えてもらえますか?基本的に、別のスレッド(UIスレッドではない)から2秒ごとにdatagridview(dgv)セルとプログレスバー(pb)を更新しようとしています。1つのスレッドがその仕事をするとき、機能はうまく機能します。ただし、最初のスレッド(スレッド1)がコントロールを更新するように2つのスレッドを設定したいと思います(私の場合、datagridviewを更新して10行を表示し、進行状況バーを50%に更新します)。スレッド1がジョブを完了するとすぐに、スレッド2が開始してコントロールを更新する必要があります(私の場合、データグリッドビューが更新され、さらに10行が表示され、進行状況バーが100%に更新されます)。以下のコードを参照してください。
c# - TaskScheduler.FromCurrentSynchronizationContext が Monotouch で同期しないのはなぜですか?
私が興味を持っているのは、これが TaskScheduler.FromCurrentSynchronizationContext() の主な意図と責任であるのに、なぜ InvokeOnMainThread を呼び出す必要があるのかということです。
iPhone アプリの Monotouch で TPL を使用して、いくつかのバックグラウンド タスクを実行し、レポーター クラスを介して UI を更新しています。しかし、 TaskScheduler.FromCurrentSynchronizationContext() は、期待どおりに UI スレッドに同期していないようです。現時点では、Xamarin のサイトのThreadingトピックで説明されているように、InvokeOnMainThread を使用して動作させることができました (ただし、まだ間違っているように感じます)。
また、BugZilla で報告された (同様の)バグが見つかりましたが、これは解決されているようです.. と、MonoTouch でバックグラウンド スレッドを使用する好ましい方法に関する別のスレッドに関する質問です。
以下は、私の質問を説明し、動作を示すコード スニペットです。
レポータークラスにはこれらのメソッドがあります
アプリケーション出力ウィンドウの結果は次のようになります。
ご覧のとおり、「Work in thread 6」は問題ありません。スレッド 6 にも報告がありますが、これは誤りです。面白いのはRegisterContinuation
、スレッド 1 で報告を行うことです!!!
進行状況: 私はまだこれを理解していません.. 誰かいますか?
.net - Windowsサービス用の.netコンポーネントのAsyncOperationManager
WinFormsに最適な.Netコンポーネントを開発しました。このコンポーネントは、を使用して、SynchronizationContext
マーシャリングの基になるスレッドからUIスレッドにイベントを発生させます(もちろん、コンポーネントはWindowsFormsSynchronizationContext
自動的に取得し、それを使用してイベントをアプリケーションのUIスレッドに送信します)。
次に、このコンポーネントを再利用してntサービスを作成します。Windowsサービスは自動的に提供しないため、このコンポーネントの基になるスレッドで発生したすべてのイベントを単一のプロセッサスレッドにマーシャリングするために(およびその)SynchronizationContext
を使用できると思いました。これは良いアプローチでしょうか?AsyncOperationManager
SynchronizationContext
私のテストではAsyncOperationManager.CreateOperation(null);
、さまざまなスレッドからの呼び出しを使用して、投稿された非同期操作の動作を確認しました(1つの実行MyService.OnStart()
メソッド...と、サービスで実行する内部処理スレッド)。驚いたことに、投稿された非同期操作のスレッドIDは常にMyService.OnStart()
メソッドを実行するものだったので、おそらくSCMスレッドでした。
これに関するMSDNのドキュメントは不足していますAsyncOperationManager.CreateOperation
が、呼び出し元のスレッドが非同期操作のマーシャリング先になると思いました。
誰かがここで光を当てることができますか?AsyncOperationManager
また、これをWindowsサービスで使用するという私の意図に何か問題がありますか?他の方法は何ですか?
c# - メインUIスレッドの継続ではSynchronizationContext.Currentがnullです
私はWinformsアプリケーションで次の問題を追跡しようとしています:
メインスレッドで実行さSynchronizationContext.Current
れるタスクの継続(つまり.ContinueWith
)でnullです(現在の同期コンテキストはであると予想されますSystem.Windows.Forms.WindowsFormsSynchronizationContext
)。
この問題を示すWinformsコードは次のとおりです。
継続から使用しようとしているため、これは私にとっての問題でBackgroundWorker
あり、BackgroundWorkerはそのイベントRunWorkerCompleted
とに現在のSynchronizationContextを使用しますProgressChanged
。BackgroundWorkerを開始すると、現在のSynchronizationContextがnullになるため、意図したとおりにイベントがメインUIスレッドで実行されません。
私の質問:
これはMicrosoftのコードのバグですか、それともどこかで間違いを犯しましたか?
追加情報:
- .Net 4.0を使用しています(.NET 4.5 RCではまだ試していません)
- これは、任意のx86 / x64 /任意のCPU(x64マシン上)のデバッグ/リリースの両方で再現できます。
- 一貫して再現します(誰かが再現できない場合は興味があります)。
- 私はBackgroundWorkerを使用するレガシーコードを持っているので、BackgroundWorkerを使用しないように簡単に切り替えることはできません
- のコードが
MyContinueWith
メインのUIスレッドで実行されていることを確認しました。 - 呼び出しが問題の原因となる理由が正確にはわかりません
StartLogicalOperation
。それが、アプリケーションで絞り込んだものです。
c# - バックグラウンド ワーカーから、Winforms アプリでホストされている WPF ダイアログから呼び出しスレッドに戻る
ウィザードと呼ぶ WPF ダイアログを起動する Winforms アプリケーションがあります。ウィザードの目的は、多数のテキスト ファイルを開き、その内容をデータベースに保存することです。これらのファイルを DB に保存するのに必要な時間は、15 秒から 60 秒以上です。ウィザード UI の応答性を高めるために、テキスト ファイルをデータベースに保存するプロセスは BackgroundWorker スレッドで実行されます。残念ながら、Winforms ホスト アプリケーションの一部のレガシー コードが原因で、ウィザードは 80 ~ 90% の時間完全に応答しません。そのため、ウィザードは独自のワーカー スレッドで起動されます。
要約すると、Winforms ホストをサポートするメイン スレッド、ウィザード スレッド、および BackgroundWorker スレッドの 3 つの主要なスレッドがあります。ユーザーは、CancelAsync メッセージを BackgroundWorker スレッドに送信するウィザードのボタンをクリックして、このエクスポート プロセスを一時停止できます。BackgroundWorker_DoWork イベント ハンドラー内で、このキャンセル メッセージを確認し、見つかった場合は処理を中止して戻ります。これにより、BackgroundWorker_RunWorkerCompleted イベント ハンドラーがトリガーされ、Thread.CurrentThread.Name を使用して制御が返されたスレッドの ID を確認できます。
ユーザーが初めて BackgroundWorker プロセスを一時停止すると、制御がウィザード スレッドに返されます。ユーザーがエクスポート プロセスを再開する場合は、RunWorkerAsync を呼び出します。これにより、BackgroundWorker_DoWork イベント ハンドラーが開始されます。観察から、このハンドラーは以前に使用したものと同じスレッドを使用せず、代わりにスレッド プールから新しいスレッドを使用することがわかります。デバッグの目的で、このスレッドに名前を付けます。
最初の BackgroundWorker スレッドの名前は MyBackgroundWorkerThread_1、2 番目のスレッドの名前は MyBackgroundWorkerThread_2 などです。
後でユーザーがプロセスを再度一時停止することを決定した場合、制御は BackgroundWorker_RunWorkerCompleted イベント ハンドラーのウィザード スレッドに返されず (初回の場合と同様)、代わりに新しいスレッドに返されます。ただし、これは致命的ではなく、ユーザーは引き続き再開でき、エクスポート プロセスは中断したところから再開されます。
ただし、データベースへの接続が失われた場合にカスタム警告ダイアログを起動しようとすると、問題が発生します。ウィザードがデータベースと通信できない場合、明らかに、ウィザードはその主要な任務を遂行できません。1 回以上の一時停止/再開サイクルの後にこのダイアログを起動すると、「多くの UI 要素がこれを必要とするため、呼び出しスレッドは STA でなければなりません」というメッセージとともに例外がスローされます。この要件のため、ウィザード スレッドは明示的に STA に設定されているため (上記の関連コードを参照)、一時停止/再開サイクルの前にデータベース接続が失われた場合でも、すべて正常に機能します。この新しいスレッドは明らかに STA ではないため、例外がスローされます。
私が試したオプションの 1 つは、DatabaseConnectivityLoss ダイアログを起動したい時点でウィザード スレッドにいるかどうかをテストすることでした。ウィザード スレッドは明示的に名前が付けられたスレッドであるため (上記のコードを参照)、現在のスレッドの name プロパティが null かどうかをテストするだけです。
これは、前述の例外なしでダイアログを起動するために正常に機能しますが、接続が復元された後にエクスポート プロセスを再開しようとすると、アプリケーションがハングします。
2 番目に試みたのは、SynchronizationContext 変数を設定して、ウィザード スレッドへの参照を保持することでした。この参照を使用して、いつでもどのスレッドが最新であるかに関係なく、ウィザード スレッドで DatabaseConnectivityLoss ダイアログを起動できることを理解していました。これを行うには、ウィザードのコンストラクターで次の変数を設定します。
ただし、後でこの SynchronizationContext を使用してコードをウィザード スレッドに強制的に戻そうとすると、失敗します。
Thread.CurrentThread.Name は通常 null を返し、それ以外の場合は "NewStaThread" を返します。この動作が断続的であることを暗示したくありません。さまざまなバリエーションを試し、さまざまな状況でさまざまな場所からこのメソッドを呼び出しただけです。
同期コンテキストはウィザード スレッドへの参照を保持するはずであり、Send メソッドを呼び出すとコールバック メソッドがウィザード スレッドで実行されるはずだというのが私の印象でした。
私の仮定のどれが無効か、あるいは解決策を提案してくれる人はいますか?
概念的には、アプリケーションを強制的に DoWork ハンドラーからウィザード スレッドに戻すか、代わりに、データベース接続損失ダイアログを起動する前に強制的にウィザード スレッドに戻す必要があると思います。匿名スレッドを開始する前に実行する必要がある STA に設定するには遅すぎるまで、匿名スレッドにアクセスできないことを理解しています。
c# - 非同期継続のためのConfigureAwaitのcontinueOnCapturedContextパラメーターとSynchronizationContextを使用したasync/await
私は最初にコードを置き、次に状況を説明し、それに基づいて私の質問をしたいと思います:
これは、.NET 4.5で実行される非常に単純なWPFサンプルであり、おそらくあまり意味がありませんが、これは私の状況を説明するのに役立つはずです。
画面に非同期クリックイベントのあるボタンがあります。GetValuesAsync
コードを見ると、キーワードawait
の使用法が2回わかります。最初の使用では、メソッドcontinueOnCapturedContext
のパラメーターをに設定しました。したがって、これは、継続が内で実行されることを必ずしも望んでいないことを示しています。ここまでは順調ですね。Task.ConfigureAwait
false
SynchronizationContext.Current
await
(メソッドを使用した) 2回目の使用では、GetStringAsync
メソッドを呼び出しませんでしたConfigureAwait
。したがって、基本的に、メソッドを継続するために現在の同期コンテキストに戻りたいGetStringAsync
ことを示しました。ご覧TextBlock.Text
のとおり、継続内に(UIスレッドに属する)プロパティを設定しようとしています。
アプリケーションを実行してボタンをクリックすると、例外が発生し、次のメッセージが表示されます。
別のスレッドがオブジェクトを所有しているため、呼び出し元のスレッドはこのオブジェクトにアクセスできません。
最初はこれは意味がなく、バグを発見したと思いましたがGetStringAsync
、UIスレッドとは異なり、同期コンテキストの知識がない別のスレッド(可能性が高い)で実行される可能性があることに気付きました。メソッドから返されるcontinueOnCapturedContext
はに設定されfalse
ます。Task
httpClient.GetAsync
これはここに当てはまりますか?また、この場合、GetStringAsync
httpClient.GetAsyncメソッドの継続がUIスレッド内で実行される可能性があるため、メソッドがUIスレッドにポストバックされる可能性はありますか?
コード内にもいくつかコメントがあります。私の質問とコード内のコメントを考慮して、ここで何かが欠けていますか?
c# - クライアント アプリでのみ SynchronizationContext を使用する方法
私のライブラリでは、SynchronizationContextを使用して、ライブラリが Windows フォームまたは WPF アプリで使用されているかどうかにかかわらず、GUI スレッドでイベントを簡単に発生できるようにします。クラスがバックグラウンド スレッドで作成された場合、SynchronizationContext は null なので、イベントを直接発生させます。
例えば:
これは問題なく動作しますが、ASP.NET アプリケーションで問題が発生するというユーザー レポートがありました。
SynchronizationContext
ASP.NET Web サイトでは null になると想定していました。AspNetSynchronizationContext のインスタンスである場合、SynchronizationContext を使用しない方法が必要ですが、System.Web への参照がなく、一般に公開されているタイプではないため、これを行うのはかなり厄介です。
私の質問は、GUI (WinForms、WPF、WinRT など) を備えたアプリケーションにいるかどうかを判断し、その設定で SynchronizationContext のみを使用する最善の方法は何ですか?
c# - 同期コンテキスト .send で値を返すことは可能ですか?
SynchronizationContext を使用して、Send を介して値 (具体的には MessageBox DialogResult) を返す必要があります (「Post」を介した非同期は必要ありません)。構文がわからないだけです。メイン フォームの IWin32Window 値に簡単にアクセスできないことが原因と考えられるメイン ウィンドウの背後に MessageBox が表示されるという問題がありました...これを使用していますが、正直言って不快です。