IObservable - замена AutoResetEvent - PullRequest
1 голос
/ 02 марта 2011

Просто интересно, как я могу заменить AutoResetEvent в приведенном ниже? Я пытался думать, как это сделать RX-способом или с задачами, но я вижу, как это сделать.

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

Ответы [ 2 ]

1 голос
/ 02 марта 2011

Рассмотрим структурирование кода следующим образом:

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, чтобы порядок выполнения не имел значения, и RefCount (), чтобы скрыть ConnectableObservable

0 голосов
/ 02 марта 2011

Я бы попросил метод вернуть 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)); 
...