2013-03-06 13 views
10

Mam ten problem z metodą w języku C#. Zrobiłem metodę, która wywołuje funkcję z biblioteki dll nazywa się Phone.GetLampMode(); Teraz Phone.GetLampMode nic nie zwraca. Dane zostaną zwrócone w przypadku zdarzenia "onGetLampModeResponse". Czy jest sposób, w jaki mogę czekać w mojej metodzie, dopóki nie otrzymam danych ze zdarzenia onGetLampModeResponse?Poczekaj wewnątrz metody, aż zostanie przechwycone zdarzenie

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

Co jest drugim parametrem GetLampMode? Niech zgadnę: obiekt, który możesz sam zdefiniować? I czy ten obiekt jest "nadawcą" w procederze obsługi zdarzeń lub wewnątrz 'e'? EDYCJA: Tak, nazywa się userState. Możesz pobrać ten stan użytkownika wewnątrz zmiennej 'e' w funkcji wywołania zwrotnego. – sinni800

+0

Mogę wymyślić jedno brzydkie rozwiązanie, definiując globalny 'bool', który jest ustawiony na' true' przez 'OnGetLampModeResponse' i sprawdzony w pętli przez' checkLamp'. –

+0

@JohnWillemse to dość brzydkie i nie powinno się tego robić, ponieważ istnieje koncepcja przekazywania zmiennych stanu do zdarzeń. – sinni800

Odpowiedz

9

Jednym z rozwiązań jest użycie AutoResetEvent:

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

UWAGA: Ad używasz Phone jako klasy/zmiennej statycznej, można pomyśleć jesteś rozwijanie na Windows Phone ... Jeśli tak jest, należy pamiętać, że cała koncepcja programowania WP i asynchronicznego jest taka, aby nie blokować wątku UI w taki sposób.

+2

Czy właśnie wprowadziłeś funkcję waitHandle w kontekście globalnym? Co się stanie, jeśli wykonasz go więcej niż raz i zaczniesz całkowicie czekać? W jaki sposób ta odpowiedź może nawet uzyskać awanse? – sinni800

+0

@ sinni800 Dobry komentarz, ale OP nie określił nic na temat wielowątkowości. Myślę, że po prostu chce coś zsynchronizować z asynchronicznego. Jeśli jest to rzeczywiście wielowątkowe, uchwyt oczekiwania powinien zostać przekazany jako parametr metody. – ken2k

+0

należy zdecydowanie przekazać jako userState, w KAŻDYM przypadku. Ryzykujesz, że wątek utknie w nieskończoność z powodu tak marnych rzeczy jak "warunki wyścigu". – sinni800

0

Wygląda na to, że istniejący model jest zbliżony do wzorca asynchronicznego opartego na zdarzeniach (EAP). Możesz zajrzeć do artykułu Interop with Other Asynchronous Patterns and Types, który opisuje, jak przekształcić taki wzór na nowszy wzorzec asynchroniczny oparty na zadaniach (TAP).

Gdy masz Task (lub Task<T>, wystarczy Wait dla niego może

+0

Tak, słowa kluczowe Async będą idealne ... – sinni800

2

Można owinąć obsługi w sposób asynchroniczny, który powinien wyglądać mniej więcej tak (niesprawdzone).

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

W swojej metodzie wywołującego, należy napisać:

ma to tę zaletę, że interfejs użytkownika doe nie blokuj, gdy proces oczekuje na odpowiedź.

Oto blog na ten temat. Zauważ, że Framework 4.5 jest wymagany.

Powiązane problemy