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

时间:2016-09-28 22:49:50

标签: c# multithreading winforms timer

我有一个带有两个独立GUI线程的应用程序,主要的Form在每个线程上运行。 (这是为了允许不同屏幕上的同时独立用户。)

每个窗口都有一个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);
    }

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的Start();中的ResetTimer()

之前我曾经看过一个类似的行为,我认为这是因为它有时会在创建父控件的句柄之前启动,而且这已经被修复了#39;如果IsHandleCreated为假,则不要尝试启动计时器 但是:
a)我甚至不确定这不仅仅是修改它的时间的变化;
b)在这种情况下,我非常确定自窗口显示以来已经创建了父句柄;
c)同样的修复工作在这里没有用。

我现在已经挖掘了一段时间并且无处可去。更糟糕的是,我似乎无法在减少的应用程序中复制该问题。但我无法想象在停止工作之后,任何会妨碍定时器调用启动的事情。

如果有人能够找出在这里发生的事情和/或找出解决方案那将会很棒。

1 个答案:

答案 0 :(得分:0)

我今天才刚刚搞清楚发生了什么,因为调试器突然停在一个完全不同的地方。

rory.ap在评论中是正确的,只有像锁等等会导致这样的死锁。然而,当我查看我的代码时,它从未点击Invoke就像这样的构造(与UI线程一样),所以我没有注意这些。

然而今天我的注意力被吸引到了,而且我在Invoke内部有lock,这导致了死锁。