2009-03-20 12 views
2

Ich arbeite an einem kleinen Projekt, wo ich zwei asynchrone Anrufe direkt hintereinander machen muss.Asynchrone Anrufe Neuling Frage

Mein Code sieht wie folgt aus etwas:

AsynchronousCall1(); 
AsynchronousCall2(); 

Das Problem, das ich habe, ist, dass beide Anrufe überall von ein bis zwei Sekunden dauern auszuführen und ich weiß nie, was ein letztes beenden wird. Nach was ich suche, ist eine Weise, zu bestimmen, wer zuletzt beendet. Wenn Call1() zuletzt beendet wird, mache ich eine Sache. Wenn Call2() zuletzt beendet wird, mache ich eine andere Sache.

+1

Dies ist eine Race-Bedingung, die darauf wartet, zu passieren. Können Sie beschreiben, welches Problem Sie lösen wollen, vielleicht können wir uns einen besseren Ansatz ausdenken. – Juliet

+0

Sie können immer eine Sperre verwenden, um sicherzustellen, dass nur einer von ihnen einen Code eingibt. Aber können Sie etwas detaillierter erklären, was Sie erreichen wollen? – Groo

+0

@Juliet: Wenn dies eine Antwort gewesen wäre, hätte ich es gewählt. Wenn ich das im Code sah, den ich behielt, vor allem mit der Zeitabhängigkeit, mit der ich zuletzt fertig war, würde ich es als Antipattern betrachten, es sei denn, der gesamte Punkt des Programms/Moduls sollte bestimmen, welche Aktivität länger dauerte. (Wenn das der Fall wäre, hätte ich beide Anrufe selbst und überprüfe einfach die Ergebnisse.) –

Antwort

2

Ich glaube, es gibt eine Methode, die ein Mitglied der Thread-Klasse ist, um einen bestimmten Thread zu überprüfen und seinen Status zu bestimmen. Die andere Möglichkeit besteht darin, stattdessen einen BackgroundWorker zu verwenden, der es Ihnen ermöglicht, durch das Erstellen separater Methoden zu definieren, was passiert, wenn dieser Thread beendet wird.

Die Option "thread-unsafe" würde eine Klassenvariable verwenden, und am Ende jedes Threads, wenn es nicht gesperrt ist/bereits den Wert des anderen Threads haben, setze es nicht. Sonst setze es.

Wenn Sie in Ihrer Hauptmethode nach dem Aufruf warten, bis alle Threads beendet sind, testen Sie die Klassenvariable.

Das wird Ihnen Ihre Antwort geben, welcher Thread zuerst fertig war.

6

Dies ist ein einfaches Beispiel für die Verwendung einer lock, um sicherzustellen, dass nur ein Thread ein Stück Code eingeben kann. Aber es ist ein allgemeines Beispiel, das für Ihre Anwendung am besten geeignet ist oder nicht. Fügen Sie Ihrer Frage einige Details hinzu, damit wir finden können, wonach Sie suchen.

void AsynchronousCall1() 
{ 
     // do some work 
     Done("1"); 
} 

void AsynchronousCall2() 
{ 
     // do some work 
     Done("2"); 
} 

readonly object _exclusiveAccess = new object(); 
volatile bool _alreadyDone = false; 
void Done(string who) 
{ 
     lock (_exclusiveAccess) 
     { 
      if (_alreadyDone) 
       return; 

      _alreadyDone = true; 
      Console.WriteLine(who + " was here first"); 
     } 
    } 
+0

+1 y, das wird funktionieren – eglasius

0

Sie können das Tafel-Entwurfsmuster überprüfen: http://chat.carleton.ca/~narthorn/project/patterns/BlackboardPattern-display.html. Dieses Muster richtet einen gemeinsamen Datenspeicher ein und ermöglicht es Agents (die nichts voneinander wissen - in diesem Fall Ihre asynchronen Aufrufe), ihre Ergebnisse an diesem gemeinsamen Speicherort zu melden. Der "Supervisor" Ihrer Tafel würde dann wissen, welcher Anruf zuerst beendet wurde und Ihr Programm entsprechend ausrichten könnte.

1

Sie können dies mit zwei ManualResetEvent Objekten tun. Die Idee ist, den Hauptthread sowohl auf unsignalisierte als auch auf asynchrone Methoden initialisieren zu lassen. Der Haupt-Thread führt dann einen WaitAny auf beiden Objekten. Wenn AsynchronousCall1 abgeschlossen ist, signalisiert es eines der Objekte. Wenn abgeschlossen ist, signalisiert es dem anderen. Hier ist Code:

ManualResetEvent Event1 = new ManualResetEvent(false); 
ManualResetEvent Event2 = new ManualResetEvent(false); 

void SomeMethod() 
{ 
    WaitHandle[] handles = {Event1, Event2}; 
    AsynchronousCall1(); 
    AsynchronousCall2(); 
    int index = WaitHandle.WaitAny(handles); 
    // if index == 0, then Event1 was signaled. 
    // if index == 1, then Event2 was signaled. 
} 

void AsyncProc1() 
{ 
    // does its thing and then 
    Event1.Signal(); 
} 

void AsyncProc2() 
{ 
    // does its thing and then 
    Event2.Signal(); 
} 

Es gibt ein paar Vorbehalte hier. Wenn beide asynchronen Methoden vor dem Aufruf von WaitAny beendet werden, ist es unmöglich zu sagen, welche zuerst abgeschlossen wurde. Auch wenn beide Methoden sehr nahe beieinander abgeschlossen sind (d. H. Anruf 1 wird abgeschlossen, dann wird Anruf 2 abgeschlossen, bevor die Wartezeit des Hauptthreads freigegeben wird), ist es unmöglich zu sagen, welcher zuerst beendet wurde.

+0

Das ändert nicht wirklich die Race-Bedingung, die bereits existiert. Behaupten Ihre Vorbehalte nicht den Sinn der gesamten Antwort? –

Verwandte Themen