2016-05-18 8 views
1

Ich bin auf einer Klasse arbeiten, die wie folgt aussieht:Ereignisse Cross-Threads aufrufen?

public class MatchmakingService { 
    private bool working; 
    private List<MatchmakingUser> matchmakingUsers; 
    // ... 

    public MatchmakingService() 
    { 
     matchmakingUsers = new List<MatchmakingUser>(); 
    } 

    public void StartService() { 
     var thread = new Thread(this.MatchmakingWork); 
     working = true; 
     thread.Start(); 
    } 

    void MatchmakingWork() { 
     while (working) 
     { 
      // some work, match found! 
      { 
        if(onMatchFound != null) 
         onMatchFound(this, new NewMatchEventArgs(matchmakingUsers[i], matchmakingUsers[j]); 
      } 
      Thread.Sleep(1000); 
     } 
    } 
} 

Normalerweise, wenn eine Übereinstimmung gefunden wird würde ich Feuer nur ein Ereignis onMatchFound und nenne ihn einen Tag, aber da der Thread des Dienstes anders, und ein Teilnehmer dieses Ereignisses wird auf einem anderen Thread sein - wie damit umzugehen? Ich habe gelesen, dass es nicht sicher ist, und wenn es wahr ist, was sind dann meine Alternativen?

Hinweis: Ich arbeite nicht mit WinForms, also keine Controls Invoke-Shenanigans.

+0

Dies ist abhängig von Situation. An sich ist nichts verkehrt, wenn sich der Ereignisabonnent in einem anderen Thread befindet (insbesondere, wenn Sie nicht auf der UI-Plattform arbeiten und nichts an den UI-Thread senden müssen). – Evk

Antwort

2

Der einfachste Weg ist das Erstellen einer Warteschlange. Es gibt mehrere Möglichkeiten, eine Warteschlange zu implementieren. Ich würde eine Warteschlange in der MatchmakingService

erstellen Verwenden Sie eine Warteschlange, um die Übereinstimmungen zu speichern, muss der andere Thread die -Methode aufrufen, um die Warteschlange zu behandeln. Das heißt, sollte der andere Thread hat eine Timer/DispatcherTimer/While mit einem Schlaf etc ...

Beispiel:

public class MatchmakingService 
{ 
    private bool working; 
    private List<MatchmakingUser> matchmakingUsers; 
    // ... 

    // the queue 
    private List<NewMatchEventArgs> _queue = new List<NewMatchEventArgs>(); 


    public MatchmakingService() 
    { 
     matchmakingUsers = new List<MatchmakingUser>(); 
    } 

    public void StartService() 
    { 
     var thread = new Thread(this.MatchmakingWork); 
     working = true; 
     thread.Start(); 
    } 

    void MatchmakingWork() 
    { 
     while (working) 
     { 
      // some work, match found! 
      { 
       lock (_queue) 
        _queue.Add(new NewMatchEventArgs(matchmakingUsers[1], matchmakingUsers[2])); 
      } 
      Thread.Sleep(1000); 
     } 
    } 

    public void RaiseEvents() 
    { 
     NewMatchEventArgs[] copyOfQueue; 

     // create a copy (bulk action) 
     lock (_queue) 
     { 
      copyOfQueue = _queue.ToArray(); 
      _queue.Clear(); 
     } 

     // handle the items 
     if (onMatchFound != null) 
      foreach (var item in copyOfQueue) 
       onMatchFound(this, item); // indices are examples 

    } 

    public event EventHandler<NewMatchEventArgs> onMatchFound; 

} 
+0

Hm Ich hatte schon eine Warteschlange für Anfragen, also ja das scheint gut, danke! – user1255410

+0

Besonders das '// create a copy (bulk action)' ist sehr nützlich, es erstellt eine Kopie der Queue und gibt die Queue für den arbeitenden Thread frei. Dies ist auch hilfreich bei Massenaktionen. Ich verwende diese Methode immer beim Empfang von Nachrichten von TCP/IP usw. oder anderen asynchronen Inhalten (wenn Invoke/Dispatcher usw. nicht verfügbar ist) –

Verwandte Themen