Pumping Windows Messages During Long Operation?

北战南征 提交于 2019-12-22 02:05:07

问题


I'm getting the following message on a big operation that I'm running:

The CLR has been unable to transition from COM context 0x1fe458 to COM context 0x1fe5c8 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.

How do I send windows messages so that this error will no longer occur on long operations?


回答1:


It's unclear exactly what the context is - are you performing some long-running task on the UI thread of a WinForms or WPF app? If so, don't do that - use BackgroundWorker, or run the task on the thread pool or a new thread directly (possibly using Control.Invoke/BeginInvoke or Dispatcher if you need to update the UI). If your big operation uses the COM component which is complaining, it'll be harder...




回答2:


As I know this thing happens with attached debugger only. You will never get this exception in production.




回答3:


I tend to use Application.DoEvents in these scenarios. I don't know whether that will work in your situation though. It requires a reference to System.Windows.Forms but will also work in Console Apps.

Alternatively you can try multi-threading your apps.




回答4:


If this happens inside a debugger it may be due to the ContextSwitchDeadlock MDA, which you can turn off (use the Exceptions window in Visual Studio). However, it is indicative of a larger problem -- you should not perform long-running operations on your UI thread.




回答5:


The traditional win32 method is:

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 );
    }
}

But I gather that you are using .NET.




回答6:


You should process your long running operation on a separate thread to avoid freezing up the UI. This will also resolve the problem above




回答7:


I know this was asked years ago, but hoping this will help others down the road. If you don't want to worry about doing a background worker, or pumping messages, a simple workaround is simply updating something on the UI. For example, I have a tool that only I use, so I don't care if it uses the UI thread. So I simply update a textbox.text on the UI to whatever I'm working on. here is a snippet of the code. This is a very hacky, and probably incorrect way to do it professionally, but it works.

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


来源:https://stackoverflow.com/questions/4806742/pumping-windows-messages-during-long-operation

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!