在应用程序启动时启动计时器间歇性死锁

问题描述:

我有一个具有两个独立GUI线程的应用程序,并且主窗体在每个线程上运行。 (这是为了允许同时在不同屏幕上的独立用户)在应用程序启动时启动计时器间歇性死锁

这些窗口中的每一个窗口都有一个InactivityTimer组件,它用于在用户在一段时间内不活动后重新回到主页。

主要功能的相关部分:

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

的静止定时器:

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)同样的修复方法没有在这里工作。

我一直在挖掘这一段时间,并获得无处不在。更糟的是,我似乎无法在削减的应用程序中复制这个问题。但我无法想象任何会阻碍计时器在停止工作后自动启动的计时器。

如果有人可以请弄清楚发生了什么事情和/或找出它的修复程序这将是惊人的。

+0

您的应用程序中是否存在您未在此显示的任何同步机制,例如锁或信号灯? –

+0

我在不同的地方使用了'lock(/ * lock object * /){}'块,但是这些都是小部分,它们做的并不多,在应用程序的完全不相关的部分使用了不同的锁对象。在最糟糕的情况下,我可能会遇到少量争用,但没有死锁。 – fweaks

+0

这些是唯一会导致死锁的事情。如果我们有机会帮助你解决问题,你需要向我们展示所有相关的代码。 –

我只是今天才知道发生了什么,因为调试器突然停在了一个完全不同的地方。

rory.ap在评论中是正确的,只有像锁等事情会导致这样的僵局。然而,当我查看我的代码时,它从来没有点击过Invoke就像这样的构造(关于UI线程),所以我没有注意到这些。

但是,今天我的注意力被吸引到它,低看,我有一个lockInvoke,这是造成死锁。