在长时间运行期间发送 Windows 消息?

发布于 2024-10-14 13:13:47 字数 395 浏览 9 评论 0原文

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

CLR 无法转换 从 COM 上下文 0x1fe458 到 COM 上下文 0x1fe5c8 60 秒。这 拥有目的地的线程 上下文/公寓最有可能 要么进行非泵送等待,要么 处理很长时间的运行 无需泵送 Windows 即可运行 消息。这种情况一般有 负面的性能影响,并可能 甚至导致应用程序变得 无响应或内存使用 随着时间的推移不断积累。到 避免这个问题,全部单身 线程公寓 (STA) 线程 应该使用泵等待原语 (例如 CoWaitForMultipleHandles)和 在长时间内定期发送消息 运行操作。

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

时光沙漏 2024-10-21 13:13:47

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

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

终弃我 2024-10-21 13:13:47

据我所知,只有附加的调试器才会发生这种情况。在生产中你永远不会遇到这个异常。

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

清风无影 2024-10-21 13:13:47

如果这种情况发生在调试器内,则可能是由于 ContextSwitchDeadlock MDA 造成的,您可以将其关闭(使用 Visual Studio 中的“异常”窗口)。然而,它表明了一个更大的问题——您不应该在 UI 线程上执行长时间运行的操作。

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.

冬天旳寂寞 2024-10-21 13:13:47

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

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

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.

原来分手还会想你 2024-10-21 13:13:47

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

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.

花想c 2024-10-21 13:13:47

我在从 WinForms 项目切换到 ConsoleApp 项目时遇到了这个问题。 Program.cs 中的 Main() 方法具有 WinForms 模板中遗留下来的不必要的 [STAThread] 属性。删除该属性使错误消失。

I encountered this when switching from a WinForms project to a ConsoleApp project. The Main() method in Program.cs had an unnecessary [STAThread] attribute leftover from the WinForms template. Removing the attribute made the error go away.

梦途 2024-10-21 13:13:47

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

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

您的好友蓝忘机已上羡 2024-10-21 13:13:47

我知道这是几年前提出的问题,但希望这能帮助其他人。如果您不想担心后台工作或发送消息,一个简单的解决方法就是更新 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.
}

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.
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文