C# 4.0 ObserveOn(Scheduler.CurrentThread)不';t使订阅的操作在原始线程上运行
我有一个执行回调的操作,它将在完成后使用泛型参数调用,即C# 4.0 ObserveOn(Scheduler.CurrentThread)不';t使订阅的操作在原始线程上运行,c#-4.0,system.reactive,C# 4.0,System.reactive,我有一个执行回调的操作,它将在完成后使用泛型参数调用,即操作。我想在操作开始时显示一个繁忙的微调器,然后在调用回调时将其移除,因此我创建了一个简单的实用程序来实现这一点。我遇到的问题是,用户希望他们的回调在原始调用线程上运行,但并不总是这样。它几乎总是在单元测试(nUnit)中完美工作,但在应用程序实际运行时(WPF、.Net 4)对某些调用不起作用 以下是我所拥有的相关信息 void WrapAsyncCallbackPattern<T>(Action<T> callb
操作
。我想在操作开始时显示一个繁忙的微调器,然后在调用回调时将其移除,因此我创建了一个简单的实用程序来实现这一点。我遇到的问题是,用户希望他们的回调在原始调用线程上运行,但并不总是这样。它几乎总是在单元测试(nUnit)中完美工作,但在应用程序实际运行时(WPF、.Net 4)对某些调用不起作用
以下是我所拥有的相关信息
void WrapAsyncCallbackPattern<T>(Action<T> callback, Action<Action<T>> actionToRun)
{
var subject = new AsyncSubject<T>();
try
{
actionToRun(
result =>
{
subject.OnNext(result);
subject.OnCompleted();
});
}
catch (Exception ex)
{
subject.OnError(ex);
}
subject
.ObserveOn(Scheduler.CurrentThread)
.Subscribe(callback, OnError);
}
您可能对调度器.CurrentThread的功能有错误的理解。我认为每个人都会犯这个错误
CurrentThread
调度程序与执行的可观察对象相关,而不是在定义(或订阅)时。考虑延迟或延迟执行。这应该是有意义的,因为无论何时跳转到不同的线程,您都需要某种方法来编组调用
所以你真正想要的是这样的东西:
var synchContext = new SynchronizationContextScheduler(
System.Threading.SynchronizationContext.Current)
subject
.ObserveOn(synchContext)
.Subscribe(callback, OnError);
或者可能:
subject
.ObserveOn(this) /* this is my current form */
.Subscribe(callback, OnError);
如果您这样做,您应该能够控制在哪个线程上运行回调
您的测试可能成功了,因为它们最终是同步执行的。您可能对调度器.CurrentThread的功能有错误的理解。我认为每个人都会犯这个错误
CurrentThread
调度程序与执行的可观察对象相关,而不是在定义(或订阅)时。考虑延迟或延迟执行。这应该是有意义的,因为无论何时跳转到不同的线程,您都需要某种方法来编组调用
所以你真正想要的是这样的东西:
var synchContext = new SynchronizationContextScheduler(
System.Threading.SynchronizationContext.Current)
subject
.ObserveOn(synchContext)
.Subscribe(callback, OnError);
或者可能:
subject
.ObserveOn(this) /* this is my current form */
.Subscribe(callback, OnError);
如果您这样做,您应该能够控制在哪个线程上运行回调
您的测试可能成功了,因为它们最终是同步执行的。单元测试实际上是为了验证它们是否在不同的线程上运行,作为最后断言的一部分。如果测试结果不正确,那么测试结果几乎是无效的。有趣的是,这个更改在应用程序运行时修复了它,但是现在测试失败了,调用线程、操作线程和回调线程都不同了。如果您有任何想法,我将添加我的测试代码。@BryanAnderson-您发布的测试代码中没有Rx。你发布了正确的测试方法吗?是的,我更新了我的方法以显示签名,所以它更清晰。在背景操作课上。Rx是类/函数的一种实现细节,因此它对使用者是隐藏的(因此是测试)。单元测试实际上是为了验证它们是否在不同的线程上运行,作为最后断言的一部分。如果测试结果不正确,那么测试结果几乎是无效的。有趣的是,这个更改在应用程序运行时修复了它,但是现在测试失败了,调用线程、操作线程和回调线程都不同了。如果您有任何想法,我将添加我的测试代码。@BryanAnderson-您发布的测试代码中没有Rx。你发布了正确的测试方法吗?是的,我更新了我的方法以显示签名,所以它更清晰。在背景操作课上。Rx是类/函数的一种实现细节,因此它对消费者是隐藏的(因此是测试)。