为非线程安全类创建一个可观察包装器



我有一个类,

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

相关内容

  • 没有找到相关文章

最新更新