3

VS 2008 でプログラムをデバッグしているときに、次のエラーに遭遇しました。

CLR は、60 秒間、COM コンテキスト 0x34fc1a0 から COM コンテキスト 0x34fc258 に移行できませんでした。宛先コンテキスト/アパートメントを所有するスレッドは、非ポンピング待機を行っているか、Windows メッセージをポンピングせずに非常に長時間実行されている操作を処理している可能性があります。この状況は通常、パフォーマンスに悪影響を及ぼし、アプリケーションが応答しなくなったり、メモリ使用量が時間の経過とともに継続的に蓄積したりする可能性さえあります。これを避けるには

コードには単純な C# タイマーしか含まれていませんが、デッドロックしているように見えます: 以下のスニペットを参照してください:

    private void RequestWork()
    {
        // The timer will be re-intialised if there are still no wating jobs in the database
        StopTimer();

        // assign all the threads some work
        InitialiseTimer();

    }



    /// <summary>
    /// Initialise a timer with a timer interval configured from app.config. Enable the timer and 
    /// register an appropriate event handler
    /// </summary>
    private void InitialiseTimer()
    {


        if (m_Timer == null)
        {
            // look up the default backoff time from the config
            string backOffInt = ConfigurationSettings.AppSettings["BackOffInterval"];

            int backoffInterval = 1000;


            m_Timer = new System.Timers.Timer();


            // set the timer interval to 5 seconds
            m_Timer.Interval = backoffInterval;

            m_Timer.Elapsed += new ElapsedEventHandler(m_Timer_Elapsed);
        }

        m_Timer.Enabled = true;
    }


    private void StopTimer()
    {

        if (m_Timer != null)
        {
            m_Timer.Enabled = false;
        }
    }

    void m_Timer_Elapsed(object p_Sender, ElapsedEventArgs p_E)
    {

        RequestWork();
    }

タイマーが実行され、経過してから再び初期化される必要があることを知っている限り、デッドロックのローカルな理由はわかりません。

このエラーメッセージをオフにする方法は知っていますが、これは解決策ではなく、問題を隠していると感じています。

4

5 に答える 5

5

デッドロック状態が確実に発生していないと思われる場合は、これをオフにすることができます。

VisualStudioの[デバッグ]->[例外]->[管理されたデバッグアシスタント]メニューを選択し、ContextSwitchDeadlockのチェックを外します

于 2008-12-02T16:48:13.200 に答える
4

これは無限ループです。この例外が発生しないようにするには、アプリケーションが少なくとも 60 秒ごとに 1 回メッセージを送信できるようにする必要があります。System.Threading.Thread.CurrentThread.Join(10) を時々呼び出してみてください。メッセージをポンピングできる他の呼び出しがあります。

于 2009-03-04T22:34:53.537 に答える
1

InitialiseTimer を呼び出すたびに、新しいイベント ハンドラーを追加しているようです。そうすれば、m_Timer_Elapsed は追加された回数だけ呼び出されます。イベント ハンドラーは 1 回だけ追加する必要があります。

于 2008-12-02T16:34:30.060 に答える
1

contextswitchdeadlock に対するボックスのチェックを外した後でも、アプリケーションがハングするか応答しない場合。メソッドの呼び出しまたは for ループの前に次の行を追加します。

C# の場合

System.Windows.Forms.Application.DoEvents();

および VB.NET / VB / ASP.NET

DoEvents()
于 2010-02-09T06:29:30.207 に答える
0

カップルの考え/質問:

1) コード スニペットは、間隔が 1 秒ごとのように見えます (コメントに記載されている 5 ではありません)。2) 大きな問題は、何をしているのRequestWork()か?

RequestWork()が行われているのかわからないため、ContextSwitchDeadlock が表示される理由についてコメントすることはできません。

この方法に関して考えるべきこと a) どれくらいの時間がかかりますか? b) GUI 要素にアクセスしていますか?

Elapsed に関する MSDN のコメント:

フォームやコントロールなどのユーザー インターフェイス要素で Timer を使用する場合は、Timer を含むフォームまたはコントロールを SynchronizingObject プロパティに割り当てて、イベントがユーザー インターフェイス スレッドにマーシャリングされるようにします。

-と-

Elapsed イベントは、ThreadPool スレッドで発生します。Elapsed イベントの処理が Interval より長く続く場合、イベントは別の ThreadPool スレッドで再び発生する可能性があります。したがって、イベント ハンドラーは再入可能である必要があります。

1 秒のタイマーがあるので、RequestWork で何が起こっているかを調べて、どれくらいの時間がかかるかを確認したいと思うかもしれません。

于 2009-01-28T22:54:34.417 に答える