1

只是想知道如何替换下面的 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;
}
4

2 回答 2

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

我们使用Publishto 以便执行顺序无关紧要,并使用 RefCount() 隐藏ConnectableObservable

于 2011-03-02T19:29:04.803 回答
0

我会让方法返回一个IObservable<LogOnResponse>,所以你不需要等到你准备好返回。您还必须注意比赛条件,因为您对 Login 的调用可能在您有机会订阅之前完成。像这样的东西应该处理竞争条件并通过返回的 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)); 
于 2011-03-02T19:42:41.377 回答