2011-03-02 65 views
1

想知道如何在下面代替AutoResetEvent?我試圖考慮如何使用RX方式或使用任務,但我可以看到如何去做。IObservable - 替換AutoResetEvent

public void LogOnResponse LogOn() 
{ 

    LogOnResponse logOnResponse = null; 
    var waitEvent = new AutoResetEvent(false); 

    var listener = _connection.LoginStatusEvent 
         .Where(x => x.LoginState == LoginState.LoggedOn 
            || x.LoginState == LoginState.LoggedRejected); 

    listener.Subscribe(x => { 
          logOnResponse = new LogOnResponse(); 
          logOnResponse.InformationMessage = x.Message; 
          logOnResponse.IsAuthenticated = x.LoginState == LoginState.LoggedOn; 
          waitEvent.Set(); 
         }); 

    connection.Login(connectionInfo); 

    waitEvent.WaitOne(2000); 

    return logOnResponse; 
} 

回答

1

考慮結構化,像這樣的代碼:

var listener = _velocityConnection.LoginStatusEvent 
    .Where(x => x.LoginState == LoginState.LoggedOn || x.LoginState == LoginState.LoggedRejected); 

var logOnResponse = listener.Select(x => 
    new LogOnResponse() { 
     logOnResponse.InformationMessage = x.Message; 
     logOnResponse.IsAuthenticated = x.LoginState == LoginState.LoggedOn; 
    } 
).Timeout(TimeSpan.FromSeconds(2), Observable.Return(new LogOnResponse() {...})) 
    .Publish() 
    .RefCount(); 

connection.Login(connectionInfo); 
return logOnResponse.First(); 

我們使用Publish這麼執行的順序並不重要,並引用次數()隱藏ConnectableObservable

+0

登錄後需要登錄「First()」嗎?它只是最初的IObservable只會在登錄後纔開始發佈結果......如果我能正確理解代碼,它會阻塞,直到它收到一些東西,但永遠不會因爲它沒有登錄。 – 2011-03-02 20:27:16

+0

此外,如果這是這種情況如果連接完成並在First()方法連接之前通過通知發佈通知,會發生什麼? – 2011-03-02 20:28:12

+0

好點 - 調整了代碼 – 2011-03-02 21:25:28

0

我會該方法返回一個IObservable<LogOnResponse>,所以你不需要等到你準備好返回。您還必須留意比賽條件,因爲您的登錄電話可能會在您有機會訂閱之前完成。像這樣的東西應該處理競爭條件,並通過返回的IObservable返回響應。你可以明顯地訂閱這個來獲得LogOnResponse,一旦它出現。

public IObservable<LogOnResponse> LogOn() 
{ 
    return Observable.CreateWithDisposable<LogOnResponse>(observer => 
    { 
     var loginDisposable = _velocityConnection.LoginStatusEvent 
         .Where(x => x.LoginState == LoginState.LoggedOn 
            || x.LoginState == LoginState.LoggedRejected) 
         .Select(x => { 
          logOnResponse = new LogOnResponse(); 
          logOnResponse.InformationMessage = x.Message; 
          logOnResponse.IsAuthenticated = x.LoginState == LoginState.LoggedOn; 
          return logOnResponse; 
         }).Take(1).Subscribe(observer); 

     connection.Login(connectionInfo); 

     return loginDisposable; 
    }); 
} 

在這裏需要注意的一件事是調用此方法只會返回IObservable。直到您訂閱,纔會調用實際登錄。

// Gets the IObservable<LogOnResult> 
var logonResponseAsObservable = LogOn(); 
//Execute the logon and wait for a response asynchronously 
logonResponseAsObservable.Subscribe(response => HandleLogOnResponse(response));