【发布时间】:2016-09-28 22:49:50
【问题描述】:
我有一个具有两个独立 GUI 线程的应用程序,主窗体在每个线程上运行。 (这是为了允许不同屏幕上的同时独立用户。)
每个窗口都有一个 InactivityTimer 组件,用于在用户处于非活动状态一段时间后将其带回主页。
main函数的相关部分:
static void Main()
{
MainWindow form1 = new MainWindow(true);
//check that we have a second screen
if (Screen.AllScreens.Length > 1)
{ //Setup the second screen on its own thread and bind events between the two
System.Threading.Thread thread = new System.Threading.Thread(() =>
{
MainWindow form2 = new MainWindow(false);
form2.FormClosed += (o, e) =>
{
form1.Invoke((MethodInvoker)delegate
{
form1.Close();//close form1 when form2 closes. we dont need vice-versa because form2 is on a background thread.
});
};
/* Logic that binds events between the two forms*/
Application.Run(form2);
})
{ IsBackground = true };
thread.Start();
}
Application.Run(form1);
}
InactivityTimer:
public partial class InactivityTimer : System.Windows.Forms.Timer, IMessageFilter
{
public InactivityTimer()
{
Initialise();
}
public InactivityTimer(IContainer container)
{
Initialise();
container.Add(this);
}
private void Initialise()
{
InitializeComponent();
Application.AddMessageFilter(this);
}
public void ResetTimer()
{
Stop();
Start();
}
public bool PreFilterMessage(ref Message m)
{
bool watching = /*logic that determines whether this is a message we are watching for (mainly mouse actions)*/;
if (watching)
{
ResetTimer();
}
return false;//do not stop the event being dispatched
}
}
当我启动应用程序时,其中一个屏幕总是先于另一个显示,这并不意外。但有时(并非总是)当我在另一个屏幕出现之前与该屏幕进行交互时,应用程序就会停止,就像死锁一样。第二个屏幕从不显示,第一个屏幕停止响应输入。
如果发生这种情况时我在调试模式下“全部中断”,则应用程序总是卡在 InactivityTimer 的 ResetTimer() 中的 Start(); 上。
我以前曾看到过类似的行为,我认为这是因为它有时在创建父控件的句柄之前就已启动,并且如果 IsHandleCreated 为 false,则通过不尝试启动计时器来“修复”该问题。
但是:
a)我什至不确定这不仅仅是修复时间的改变;
b) 在这种情况下,我相当肯定父句柄已经创建,因为窗口正在显示;
c) 同样的修复在这里没有奏效。
我已经对此进行了一段时间的研究,但一无所获。更糟糕的是,我似乎无法在精简的应用程序中复制该问题。但我无法想象有什么会妨碍计时器在停止后自行调用 start 工作正常。
如果有人能弄清楚这里发生了什么和/或找出解决方法,那将是惊人的。
【问题讨论】:
-
您的应用程序中是否有您未在此处显示的同步机制,例如锁还是信号量?
-
我在各个地方都在使用
lock(/*lock object*/){}块,但是这些都是小部分,并没有做很多事情,并且在应用程序的完全不相关的部分中使用了不同的锁对象。在最坏的情况下,我可能会遇到少量争用,但不会出现死锁。 -
只有这些会导致死锁。如果我们有机会帮助您解决问题,您需要向我们展示所有相关代码。
-
但是我的任何锁怎么可能调用
Start()(直接从windows库继承)阻塞? -
我不确定。你能把它归结为MCVE吗?
标签: c# multithreading winforms timer