2016-09-28 1 views
-2

Ich habe eine Anwendung mit zwei separaten GUI-Threads, und die Hauptform wird auf jedem Thread ausgeführt. (Dies ermöglicht gleichzeitig unabhängigen Benutzern auf verschiedenen Bildschirmen.)Starten eines Timers intermittierend Deadlocks beim Start der Anwendung

Jedes dieser Fenster verfügt über eine InactivityTimer-Komponente, mit der der Benutzer nach einer gewissen Zeit der Inaktivität auf die Startseite zurückgeleitet wird.

Die entsprechenden Teile der Hauptfunktion:

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

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

Wenn ich die Anwendung zu starten, einem der Bildschirme zeigt sich immer vor dem anderen, die nicht unerwartet . Aber manchmal (nicht immer) Wenn ich mit diesem Bildschirm interagieren, bevor der andere aufgetaucht ist, stoppt die Anwendung nur, als ob deadlocked. Der zweite Bildschirm wird nie angezeigt und der erste Bildschirm reagiert nicht mehr auf Eingaben.

Wenn ich "Break All" im Debug-Modus, wenn dies passiert, ist die Anwendung immer auf die Start(); in der ResetTimer() des InoctivityTimer stecken.

Ich habe schon einmal ein ähnliches Verhalten mit einem Timer gesehen, von dem ich glaubte, dass er manchmal gestartet wurde, bevor das Handle des übergeordneten Steuerelements erstellt wurde. Das wurde behoben, indem ich nicht versuchte, den Timer zu starten, wenn IsHandleCreated falsch war.
Aber:
a) Ich weiß nicht einmal sicher, dass es nicht nur eine Änderung des Timings war, die es repariert;
b) In diesem Fall bin ich ziemlich sicher, dass das Eltern-Handle bereits erstellt wurde, da das Fenster angezeigt wird;
c) Derselbe Fix hat hier nicht funktioniert.

Ich habe mich schon eine Weile damit beschäftigt und komme nirgendwohin. Schlimmer noch, ich kann das Problem nicht in einer abgespeckten Anwendung reproduzieren. Aber ich kann mir einfach nicht vorstellen, dass irgendwas, das einem Timer in die Quere kommen würde, nach dem Stop gut funktionieren würde.

Wenn jemand kann bitte herausfinden, , was hier los ist und/oder herauszufinden, eine Lösung dafür das wäre erstaunlich.

+0

Gibt es Synchronisierungsmechanismen in Ihrer Anwendung, die Sie hier nicht anzeigen, z. Schlösser oder Semaphore? –

+0

Ich benutze 'lock (/ * lock object * /) {}' Blöcke an verschiedenen Stellen, aber dies sind alles kleine Abschnitte, die nicht viel tun, und verschiedene Lock-Objekte werden in völlig unabhängigen Abschnitten der Anwendung verwendet. Im schlimmsten Fall könnte ich eine kleine Menge Streit bekommen, aber keine Deadlocks. – fweaks

+0

Das sind die einzigen Dinge, die einen Deadlock verursachen würden.Sie müssen uns allen relevanten Code zeigen, wenn wir eine Chance haben, Ihnen zu helfen, es herauszufinden. –

Antwort

0

Ich hatte gerade erst Glück, herauszufinden, was vor sich ging, weil der Debugger plötzlich an einem völlig anderen Ort anhielt.

Rory.ap war in den Kommentaren richtig, dass nur Dinge wie Schlösser usw. einen solchen Deadlock verursachen würden. Als ich jedoch über meinen Code schaute, klickte er nie, dass Invoke sich wie ein solches Konstrukt verhält (mit dem UI-Thread), also habe ich diese nicht beachtet.

Aber heute wurde meine Aufmerksamkeit darauf gelenkt und Low-und-siehe ich habe eine Invoke innerhalb einer lock, die einen Deadlock verursacht.

Verwandte Themen