我有一个类,
public class Test
{
public int Calc();
}
,它要求所有对Calc的调用都在与创建Test的线程相同的线程上执行。我需要创建Test一次(昂贵的操作),并多次调用Calc。
我想有一个包装,让我调用Calc异步:
public class TestWrapper
{
private Test _test;
public IObservable<int> Calc();
}
一种方法是创建一个BackgroundWorker或Thread,并使用它作为对Test的所有操作都在同一线程上的保证。为简单起见,我们可以假设对Calc()的所有调用将按顺序执行,因此无需担心排队问题。
有没有更优雅的RX方法?
如果在创建TestWrapper
时创建Test
是可能的,那么这个类似乎符合您的要求:
public class TestWrapper
{
public TestWrapper(Func<Test> factory)
{
_scheduler = new EventLoopScheduler();
_test = Observable.Start(factory, _scheduler).First();
}
private readonly EventLoopScheduler _scheduler;
private readonly Test _test;
public IObservable<int> Calc()
{
return Observable.Start(() => _test.Calc(), _scheduler);
}
}
它的用法如下:
var testWrapper = new TestWrapper(() => new Test());
testWrapper.Calc().Subscribe(x => { });
我已经测试过了,它在执行Calc
的同一线程上创建了Test
。另一方面,订阅是在创建testWrapper
本身的同一线程上处理的(即调用线程)。
所以从评论和重读你的问题,我收集你想反复调用Calc()在一个恒定的线程,并有返回结果可用的IObservable<Int>()
?
在这种情况下,我将使用Observable.Create
来包装Test
类,并使用EventLoopScheduler
来确保对Calc的调用在单个线程上。
public class TestWrapper
{
private Test _test;
public IObservable<int> Calc()
{
return Observable.Create(obsvr =>
{
var fixedThreadsched = new EventLoopScheduler();
var disp = new BooleanDisposable();
while (!disp.IsDisposed)
{
fixedThreadsched.Schedule(() => obsvr.OnNext(_test.Calc()));
}
return disp;
});
}
}
在创建Test
实例时使用ThreadLocal<T>
类:
var MyTEST = new ThreadLocal<Test>();
那么你可以使用MyTEST.Value.Calc ()
的任何调用…
另一个选项是在包装器类的Test成员上使用put [ThreadStatic]
…见http://msdn.microsoft.com/en-us/library/system.threadstaticattribute.aspx
根据您是否需要多个Test
实例,您可以将其设置为Singleton