Read
方法的正确方法是什么?
public int Method()
{
return Read();
}
我已经尝试过这样做,但是当超时发生时,我的应用程序会完全关闭,所以我猜它有问题。
public int Method()
{
return Observable.Start(() => Read()).Timeout(TimeSpan.FromSeconds(2)).Wait();
}
Timeout
,因为它确实通过异常进行控制,我们知道这是不好的。我倾向于使用这种模式:
Observable
.Amb(
Observable.Timer(TimeSpan.FromSeconds(2.0)).Select(x => (int?)null),
Observable.Start(() => (int?)Read()))
Amb
在第一个可观察量上触发以产生一个值,然后忽略另一个。只需设置一个适当的返回值,在您的情况下,它是
int?
允许号码通过,或者是
null
如果超时。然后我利用我们可以等待可观察值的最后一个值这一事实,我这样做了:
public async Task<int?> Method() =>
await
Observable
.Amb(
Observable.Timer(TimeSpan.FromSeconds(2.0)).Select(x => (int?)null),
Observable.Start(() => (int?)Read()))
.LastAsync();
如果你不想使用任务那么你仍然可以使用Wait()
:
public int? Method() =>
Observable
.Amb(
Observable.Timer(TimeSpan.FromSeconds(2.0)).Select(x => (int?)null),
Observable.Start(() => (int?)Read()))
.Wait();
Wait
方法会阻塞,直到
Observable
完成或引发异常。如果超时,
Timeout
运算符将抛出
TimeoutException
。由于
Wait
不处理异常,它会传播此异常,导致应用程序崩溃。您可以使用
Subscribe
代替
Wait
并处理异常:
public int Method()
{
int result = 0;
var resetEvent = new AutoResetEvent(false);
Observable
.Start(() => Read())
.Timeout(TimeSpan.FromSeconds(2))
.Subscribe(
x => { result = x; resetEvent.Set(); }, // onNext
ex => { /* handle exception */ resetEvent.Set(); } // onError
);
resetEvent.WaitOne(); // Wait until the Observable completes or an exception is thrown
return result;
}
此代码启动一个包装 Observable
方法的
Read
。它要么完成并返回结果(分配给
result
),要么失败并返回
TimeoutException
。无论哪种情况,都会向
AutoResetEvent
发出信号,从而允许
WaitOne
方法完成并允许
Method
方法返回结果。确保将
/* handle exception */
替换为您自己的异常处理代码。例如,您可以将
result
设置为指示超时的特殊值,或者您可以记录异常。最后一件事:由于
Method
,
resetEvent.WaitOne()
仍然处于阻塞状态。这对于控制台应用程序来说可能没问题,但在 GUI 应用程序中,这会冻结 UI,直到
Read
方法完成或发生超时。如果您想避免阻塞,则需要使用不同的设计,例如使
Method
异步或提供在
Read
方法完成时调用的回调。