web-dev-qa-db-ja.com

長時間の操作中にWindowsメッセージをポンプしますか?

実行中の大きな操作について次のメッセージが表示されます。

CLRは、COMコンテキスト0x1fe458からCOMコンテキスト0x1fe5c8に60秒間遷移できませんでした。宛先のコンテキスト/アパートメントを所有するスレッドは、ほとんどの場合、非ポンプ待機を実行しているか、Windowsメッセージをポンプ送信せずに非常に長時間実行されている操作を処理しています。この状況は通常、パフォーマンスに悪影響を及ぼし、アプリケーションが応答しなくなったり、メモリ使用量が時間の経過とともに継続的に蓄積したりする可能性があります。この問題を回避するには、すべてのシングルスレッドアパートメント(STA)スレッドがポンピング待機プリミティブ(CoWaitForMultipleHandlesなど)を使用し、長時間実行される操作中に定期的にメッセージをポンピングする必要があります。

このエラーが長時間の操作で発生しないようにするには、Windowsメッセージを送信する方法を教えてください。

22
sooprise

コンテキストが正確に何であるか不明です。WinFormsまたはWPFアプリのUIスレッドで長時間実行されているタスクを実行していますか?その場合は、それを行わないでください。BackgroundWorkerを使用するか、スレッドプールまたは新しいスレッドでタスクを直接実行します(おそらくControl.Invoke/BeginInvokeまたはDispatcher(UIを更新する必要がある場合)。あなたの大きな操作ses不平を言っているCOMコンポーネントなら、それはより難しくなるでしょう...

19
Jon Skeet

私が知っているように、これは付属のデバッガでのみ起こります。本番環境ではこの例外は発生しません。

6
Tony Kh

これらのシナリオでは Application.DoEvents を使用する傾向があります。それがあなたの状況でうまくいくかどうかはわかりません。 System.Windows.Formsへの参照が必要ですが、コンソールアプリでも機能します。

または、アプリのマルチスレッド化を試すこともできます。

3

これがデバッガー内で発生する場合は、ContextSwitchDeadlock MDAが原因である可能性があります。これはオフにすることができます(Visual Studioの[例外]ウィンドウを使用)。ただし、これはより大きな問題を示しています。UIスレッドで長時間実行オペレーションを実行しないでください。

3

従来のwin32メソッドは次のとおりです。

void PumpMessages()
{
    MSG msg;
    for( ;; ) {
        if( !PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ) {
            return;
        }
        if( msg.message == WM_QUIT ) {
            s_stopped = true;
            return;
        }
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
}

しかし、私はあなたが.NETを使用していることを収集します。

1
user590812

WinFormsプロジェクトからConsoleAppプロジェクトに切り替えるときにこれが発生しました。 _Program.cs_のMain()メソッドに、WinFormsテンプレートの不要な_[STAThread]_属性が残っていました。属性を削除すると、エラーは解消されました。

0
kylejrp

UIのフリーズを回避するために、別のスレッドで長時間実行オペレーションを処理する必要があります。これは上記の問題も解決します

0
WraithNath

私はこれが何年も前に尋ねられたことを知っていますが、これが将来他の人を助けることを願っています。バックグラウンドワーカーの実行やメッセージのポンプ送信を心配したくない場合は、簡単な回避策として、UIで何かを更新するだけです。たとえば、私だけが使用するツールがあるので、UIスレッドを使用するかどうかは気にしません。そのため、UIのtextbox.textを自分が作業しているものに更新するだけです。これがコードのスニペットです。これは非常にハッキーであり、おそらく専門的にそれを行うには正しくない方法ですが、動作します。

for (int i = 0; i < txtbxURL.LineCount; i++)
{
    mytest.NavigateTo(mytest.strURL);
    mytest.SetupWebDoc(mytest.strURL);
    strOutput = mytest.PullOutPutText(mytest.strURL);
    strOutput = mytest.Tests(strOutput);
    mytest.CheckAlt(mytest.strURL);
    mytest.WriteError(txtbxWriteFile.Text);
    txtblCurrentURL.Text = mytest.strURL;
    //This ^^^ is what is being updated, which keeps the thread from throwing the exception noted above.
}
0
Moose