长时间运行时泵送Windows消息?

时间:2011-01-26 16:04:04

标签: c# message-pump

我在正在运行的大型操作上收到以下消息:

  

CLR无法过渡   从COM上下文0x1fe458到COM   上下文0x1fe5c8持续60秒。该   拥有目的地的线程   上下文/公寓是最有可能的   或者做一次非抽水等待或者   处理很长时间   没有泵Windows的操作   消息。这种情况一般都有   负面的业绩影响和可能   甚至导致应用程序成为   无响应或内存使用   随着时间的推移不断积累。至   一切都避免这个问题   线程公寓(STA)线程   应该使用抽等待原语   (例如CoWaitForMultipleHandles)和   经常在长时间内发送消息   正在运行。

如何发送Windows消息,以便在长时间操作中不再出现此错误?

8 个答案:

答案 0 :(得分:19)

目前尚不清楚上下文的确切含义 - 您是否在WinForms或WPF应用程序的UI线程上执行了一些长时间运行的任务?如果是这样,请不要这样做 - 使用BackgroundWorker,或直接在线程池或新线程上运行任务(如果需要更新UI,可能使用Control.Invoke/BeginInvokeDispatcher )。如果您的大型操作使用抱怨的COM组件,那就更难......

答案 1 :(得分:6)

我知道这件事只发生在附加的调试器上。你永远不会在生产中得到这个例外。

答案 2 :(得分:3)

我倾向于在这些场景中使用Application.DoEvents。我不知道这是否适合你的情况。它需要引用System.Windows.Forms,但也可以在Console Apps中使用。

或者,您可以尝试对应用进行多线程处理。

答案 3 :(得分:3)

如果在调试器中发生这种情况,可能是由于ContextSwitchDeadlock MDA,您可以关闭它(使用Visual Studio中的Exceptions窗口)。但是,这表明存在更大的问题 - 您不应该在UI线程上执行长时间运行的操作。

答案 4 :(得分:1)

传统的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。

答案 5 :(得分:0)

您应该在单独的线程上处理长时间运行的操作,以避免冻结UI。这也将解决上面的问题

答案 6 :(得分:0)

我知道这是多年前提出来的,但我希望这会有助于其他人。如果您不想担心做背景工作者或抽取消息,一个简单的解决方法就是在UI上更新某些内容。例如,我有一个只使用的工具,所以我不关心它是否使用UI线程。所以我只需将UI上的textbox.text更新为我正在处理的任何内容。这是一段代码。这是一个非常hacky,可能是不正确的专业方式,但它的工作原理。

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.
}

答案 7 :(得分:0)

从WinForms项目切换到ConsoleApp项目时遇到了此问题。 Main()中的Program.cs方法具有WinForms模板中多余的[STAThread]属性。删除该属性会使错误消失。