gpt4 book ai didi

c# - 接口(interface)在多线程 C# 应用程序中卡住

转载 作者:太空宇宙 更新时间:2023-11-03 19:31:22 29 4
gpt4 key购买 nike

我有一个卡住界面的 c# .NET 多线程应用程序。不同寻常的是界面不会卡住,除非我让系统闲置足够长的时间让屏幕保护程序启动(这需要我重新输入密码才能重新获得对系统的访问权限)。当界面再次可见时(在我成功输入密码后)界面被锁定。只要我不让屏保启动,那么界面就不会死机。

我应该指出,我有两个不同的可执行文件访问同一个 dll,无论我使用哪个应用程序访问 DLL,都会出现此问题。这似乎暗示问题出在 DLL 中,因为除了它们与 DLL 的关系之外,这两个应用程序 (C++/MFC) 和 (C#/.NET) 完全不同。

两个 exe 在如何与 DLL 交互方面执行相似的步骤。他们调用 dll 来设置串行端口通信,在 DLL 中打开一个状态窗口,在 DLL 中启动一个线程来监视通信端口,然后在主应用程序中启动一个线程来监视 dll 中的堆栈。

当 DLL 中的线程从 comm 端口获取数据时,会对其进行解析并将其结果放在堆栈上,然后通过委托(delegate)将其发布到状态窗口。当 exe 中的线程看到堆栈中的数据时,它会在主窗口中输出数据,同样使用委托(delegate)。

我发现如果我将代码添加到 DLL 内的线程,使其每 30 秒调用一次 Application.DoEvents(),界面将被卡住大约 30 秒,然后像往常一样恢复事件。我认为有什么东西阻塞了主线程并强制 DoEvents() 触发似乎打破了锁,但我不知道是什么导致了这个锁。

这个问题在我的开发机器和测试机器上都会出现。

我已经尝试完全删除 DLL 中状态窗口的数据输出,但这没有任何区别。

我从事多线程编程多年,从未见过这样的事情;因此,我们将不胜感激任何建议。

谢谢。

最佳答案

当您使用非标准方式初始化用户界面时,SystemEvents 类通常会引发此问题。特别是使用线程。启动程序,Debug + Break All,Debug + Windows + Threads。如果您看到一个名为“.NET SystemEvents”的线程,那么您肯定会挂起这个线程。

一些背景知识:SystemEvent 类同时支持控制台模式应用程序和 GUI 应用程序。对于后者,它应该在 UI 线程上触发其事件处理程序。第一次订阅其中一个事件时,它会创建一个不可见的小帮助窗口来获取系统通知。它可以通过两种方式做到这一点,即在调用线程上创建窗口或启动辅助线程。它根据 Thread.GetApartmentState() 的值做出决定。如果它是 STA,那么它可以在调用线程上创建窗口,并且所有事件回调都可以正确地编码到该线程。

如果您创建的第一个 窗口不是在 UI 线程上创建的,就会出错。例如启动画面。该窗口可能包含对 UserPreferenceChanged 等系统事件感兴趣的控件,因此它们可以正确地重新绘制自己。它现在使用辅助线程,任何事件都将从该辅助线程而非 UI 线程中触发。毒害任何在 UI 线程上运行的窗口。出于某种神秘原因,从锁定的工作站(包括屏幕保护程序)切换出 session 很可能会导致死锁。您可能还会偶尔看到绘画事故,这是使用来自错误线程的窗口的不那么令人讨厌的结果。

除了修复初始化顺序之外,解决方法是在创建任何窗口之前将其放入您的 Main() 方法中:

Microsoft.Win32.SystemEvents.UserPreferenceChanged += delegate { };

关于c# - 接口(interface)在多线程 C# 应用程序中卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4659283/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com