2013-03-06 6 views
10

Ich habe dieses Problem mit einer Methode in C#. Ich machte eine Methode, die eine Funktion aus einer DLL aufgerufen wird Phone.GetLampMode(); Nun Phone.GetLampMode gibt nichts zurück. Die Daten werden in einem Ereignis mit dem 'onGetLampModeResponse'-Ereignis zurückgegeben. Gibt es eine Möglichkeit, wie ich in meiner Methode warten kann, bis ich die Daten vom onGetLampModeResponse-Ereignis bekomme?Warten Sie innerhalb Methode, bis Ereignis erfasst wird

public bool checkLamp(int iLamp) 
{ 
    Phone.ButtonIDConstants btn = new Phone.ButtonIDConstants(); 
    btn = Phone.ButtonIDConstants.BUTTON_1; 
    btn += iLamp; 
    Phone.GetLampMode(btn, null); 

    return true; 
} 

private void Phone_OnGetLampModeResponse(object sender, Phone.GetLampModeResponseArgs e) 
{ 
    var test = e.getLampModeList[0].getLampMode.ToString();  
} 
+1

Was der zweite Parameter von GetLampMode ist? Lass mich raten: Ein Objekt, das du selbst definieren kannst? Und ist das Objekt der "Sender" im Event-Handler oder im "e"? EDIT: Ja ist es, es heißt UserState. Sie können diesen userState innerhalb der Variable 'e' in der Callback-Funktion abrufen. – sinni800

+0

Ich kann mir eine hässliche Lösung vorstellen, indem ich ein globales 'bool' definiere, das von' OnGetLampModeResponse' auf 'true' gesetzt und in einer Schleife mit' checkLamp' überprüft wird. –

+0

@ John Willemse das ist ziemlich hässlich und sollte nicht getan werden, da das Konzept der Übergabe von Zustandsvariablen an Ereignisse existiert. – sinni800

Antwort

9

Eine Lösung ist AutoResetEvent zu verwenden:

public bool checkLamp(int iLamp) 
{ 
    Phone.ButtonIDConstants btn = new Phone.ButtonIDConstants(); 
    btn = Phone.ButtonIDConstants.BUTTON_1; 
    btn += iLamp; 

    AutoResetEvent waitHandle = new AutoResetEvent(false); 

    // Pass waitHandle as user state 
    Phone.GetLampMode(btn, waitHandle); 

    // Wait for event completion 
    waitHandle.WaitOne(); 

    return true; 
} 

private void Phone_OnGetLampModeResponse(object sender, Phone.GetLampModeResponseArgs e) 
{ 
    var test = e.getLampModeList[0].getLampMode.ToString(); 

    // Event handler completed 
    // I guess there is some UserState property in the GetLampModeResponseArgs class 
    ((AutoResetEvent)e.UserState).Set(); 
} 

HINWEIS: Ad Sie verwenden Phone als statische Klasse/variabel, man denken, können Sie sich auf Windows Phone entwickelst ... Wenn dies der Fall ist, beachten Sie, dass das gesamte Konzept von WP und asynchronen Programmierung zu nicht den UI-Thread in einer solchen Weise sperren.

+2

Hast du gerade den waitHandle in den globalen Kontext gestellt? Was ist, wenn Sie es mehr als einmal ausführen und Ihr Warten vollständig hängen bleibt? Wie kann diese Antwort überhaupt aufgeklärt werden? – sinni800

+0

@ sinni800 Guter Kommentar, aber das OP hat nichts über Multithreading spezifiziert. Ich denke, er möchte nur etwas von async synchronisieren. Wenn es tatsächlich multi-threaded ist, sollte das Wait-Handle als Parameter der Methode übergeben werden. – ken2k

+0

sollte es in jedem Fall definitiv als userState übergeben werden. Du riskierst einen Faden, der wegen so mieser Dinge wie "Rassenbedingungen" unendlich feststeckt. – sinni800

0

Es sieht so aus, als ob das vorhandene Modell nahe an dem ereignisbasierten asynchronen Muster (EAP) liegt. Vielleicht möchten Sie sich den Artikel Interop with Other Asynchronous Patterns and Types ansehen, der beschreibt, wie ein solches Muster in das neuere Task-basierte Async Pattern (TAP) konvertiert wird.

Sobald Sie eine Task (oder Task<T>, können Sie einfach Wait es

+0

Ja, die Async-Schlüsselwörter wären perfekt .. – sinni800

2

Sie den Handler in einem asynchronen Verfahren wickeln kann, was in etwa so aussehen sollte (nicht getestet).

public async Task<bool> checkLamp(int iLamp) 
{ 
    Phone.ButtonIDConstants btn = new Phone.ButtonIDConstants(); 
    btn = Phone.ButtonIDConstants.BUTTON_1; 
    btn += iLamp; 

    var tcs = new TaskCompletionSource<bool>(); 
    var handler = (sender, e) => { 
     Phone.OnGetLampModeResponse -= handler; 
     var test = e.getLampModeList[0].getLampMode.ToString(); 
     tcs.SetResult(true); 
    }; 
    Phone.OnGetLampModeResponse += handler; 

    Phone.GetLampMode(btn, null); 

    return tcs.Task; 
} 

In Ihrem Rufmethode, würden Sie schreiben:

Dies hat den Vorteil, dass Ihre Benutzeroberfläche doe hat s blockiert nicht, während der Prozess auf die Antwort wartet.

Hier ist ein Blogeintrag zu diesem Thema. Beachten Sie, dass Framework 4.5 erforderlich ist.

Verwandte Themen