2016-02-23 56 views
2

我一直在调查SynchronizationContext,这些文章(Understanding SynchronizationContext,ExecutionContext vs SynchronizationContext)真的帮助我,但是 - 当然 - 还有很多问题。如何正确覆盖自定义SynchronizationContext中的Post方法?

我想实现我自己的SynchronizationContext类,该类继承自基类,以便我可以在任何Task(用于自定义消息循环,调速,跟踪等)的上下文中使用它。是这样的:

public class SyncContext : System.Threading.SynchronizationContext 
{ 

    public SyncContext() : base() 
    { 
    } 

    public override void Send(Threading.SendOrPostCallback d, object state) 
    { 
     base.Send(d, state); 
    } 

    public override void Post(Threading.SendOrPostCallback d, object state) 
    { 
     base.Post(d, state); 
    } 
} 

虽然base.Send似乎做什么期望(同步执行回调),base.Post似乎没有做任何事情。关于Post方法微软指出:

在派生类中重写,调度一个异步消息 到同步上下文。

我猜的基类不能被指责为没有异步机制来实现,而应该当base.Post被调用或发生的事情怎么可能是正确的/更好的实现看看吗?我的一般做法是否已经产生误导?

感谢您的努力!

后续问题:执行自定义TaskScheduler也许是更好的方法 - 也许TaskScheduler that uses a dedicated thread本质上是我所需要的?

+0

这是一个SynchronizationContext的关键,没有别的问题。如果你不知道如何写它,那么你不能实现一个。它必须让'd'代码在另一个**特定的**线程上运行。这样的线程必须解决[生产者 - 消费者问题](https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem)。像Winforms或WPF或UWP使用的调度器循环是标准解决方案。 –

+0

@Hans:我想我已经成功地实现了一个带有阻塞队列的消息循环,但是现在我正在寻找一个可以放入的包装器。我只是想知道在SynchronizationContext中实现了Post方法的用法基类,即为什么它不是抽象的? – mike

+0

它不是抽象的,因为SychronizationContext知道如何实现它。通过不同步任何东西,委托在一个线程池线程上运行。没有用,你必须重写它,你的Post()方法只需要将委托添加到该队列中。 Send()方法必须执行相同的操作*和*等待队列条目被占用。例如,这需要将AutoResetEvent包含在队列条目中。请记住,您正在重新创建现有的。NET SychronizationContext实现,就像[此代码](http://stackoverflow.com/a/21684059/17034)所使用的类型。 –

回答

0

如果您有自己的消息循环,则需要在SynchronizationContext中捕获它,因此当另一个线程调用SynchronizationContext.Post时,必须将回调操作添加到该消息循环中。

SynchronizationContext作为ExecutionContext的一部分“流动”,但并非总是如此,因此您需要在代码中处理流(如果可能)。

Post方法的默认实现排队一个工作线程的动作(得到了与ILSpy):

public virtual void Post(SendOrPostCallback d, object state) 
{ 
    ThreadPool.QueueUserWorkItem(new WaitCallback(d.Invoke), state); 
} 

但最大的问题是为什么你需要有自己的SynchronizationContext?如果只是为了好玩 - 那很好,否则你做的很先进,也许其他现有的更简单的机制可以解决这个问题。

相关问题