2016-09-28 13 views
-2

私は2つの別々の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); 
    } 

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

は、画面のいずれかが常に他の前に現れ、予想外ではありません。しかし、時には(ではなく、いつも)、他のものが表示される前にその画面とやり取りすると、アプリケーションはデッドロックしたように停止します。 2番目の画面が表示されず、最初の画面が入力に応答しなくなります。

この場合、デバッグモードで「すべてブレーク」を実行すると、アプリケーションは常にInactivityTimerのResetTimer()Start();にスタックされます。

私は、親コントロールのハンドルが作成される前に開始されていて、IsHandleCreatedがfalseの場合にタイマーを開始しようとしないことで '修正'されていたと考えていました。
しかし、
a)私はそれがそれを固定するタイミングの変化だけではないことを確かに知りません。
b)この場合、ウィンドウが表示されてから親ハンドルが既に作成されていることがわかります。
c)同じ修正がここでは機能しませんでした。

私は今これを掘り下げていて、どこにもいません。さらに悪いことに、私は、問題のあるアプリケーションで問題を再現することはできません。しかし、私はちょうどうまく働いた停止の後にそれ自身の上でタイマー呼び出しを開始する方法になるだろう何かを想像することはできません。

ここでは何が起こっているのかを把握してください。また、修理を考えてみるとというのはすばらしいでしょう。

+0

ここには表示されていない同期メカニズムがアプリケーションにありますか?ロックやセマフォ? –

+0

私はさまざまな場所で 'lock(/ * lock object * /){}'ブロックを使用していますが、これらはすべて小規模なセクションであり、アプリケーションの完全で無関係なセクションでは異なるロックオブジェクトが使用されます。最悪の場合、私は少量の競合を得るかもしれませんが、デッドロックはありません。 – fweaks

+0

これらは、デッドロックを引き起こす唯一のものです。あなたがそれを理解するチャンスを得るためには、関連するすべてのコードを表示する必要があります。 –

答えて

0

私は今日、デバッガが突然完全に別の場所で停止したため、何が起きているのかを理解することに幸運でした。

rory.apは、ロックなどのようなものだけがそのようなデッドロックを引き起こすというコメントでは正しいです。しかし、自分のコードを見ていたときに、それをクリックしたことはありませんでした。Invokeはそのような構造(UIスレッド)のように振る舞いました。

今日私の注意が引かれて、私はの中にInvokeがあり、デッドロックの原因となっています。

関連する問題