我在正在运行的大型操作上收到以下消息:
CLR无法过渡 从COM上下文0x1fe458到COM 上下文0x1fe5c8持续60秒。该 拥有目的地的线程 上下文/公寓是最有可能的 或者做一次非抽水等待或者 处理很长时间 没有泵Windows的操作 消息。这种情况一般都有 负面的业绩影响和可能 甚至导致应用程序成为 无响应或内存使用 随着时间的推移不断积累。至 一切都避免这个问题 线程公寓(STA)线程 应该使用抽等待原语 (例如CoWaitForMultipleHandles)和 经常在长时间内发送消息 正在运行。
如何发送Windows消息,以便在长时间操作中不再出现此错误?
答案 0 :(得分:19)
目前尚不清楚上下文的确切含义 - 您是否在WinForms或WPF应用程序的UI线程上执行了一些长时间运行的任务?如果是这样,请不要这样做 - 使用BackgroundWorker
,或直接在线程池或新线程上运行任务(如果需要更新UI,可能使用Control.Invoke/BeginInvoke
或Dispatcher
)。如果您的大型操作使用抱怨的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]
属性。删除该属性会使错误消失。