2016-02-23 3 views
2

Я изучаю SynchronizationContext, и эти статьи (Understanding SynchronizationContext, ExecutionContext vs SynchronizationContext) действительно помогли мне, но, конечно же, осталось много вопросов.Как правильно переопределить метод Post в пользовательском SynchronizationContext?

Я хотел бы реализовать свой собственный класс 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 Microsoft заявляет:

При переопределении в производном классе, отправляет асинхронное сообщение в контекст синхронизации.

Я предполагаю, что базовый класс не может быть обвинен, не имея механизм асинхронной реализации, но то, что должно произойти, когда 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: Я думаю, что я успешно реализовал цикл сообщений с блокирующей очередью, но теперь я ищу оболочку, которую я могу вставить. Мне просто интересно, что использование метода Post реализовано в SynchronizationContext базовый класс, то есть почему он не был объявлен абстрактным? – mike

+0

Это не абстрактно, потому что SychronizationContext знает, как его реализовать. Не синхронизируя ничего, делегат работает в потоке потока. Не полезно, вам придется переопределить его, ваш метод Post() просто должен добавить делегата в эту очередь. Метод Send() должен делать то же самое * и * ждать, пока запись в очередь будет потребляться. Для этого требуется, скажем, AutoResetEvent для включения в запись очереди. Имейте в виду, что вы повторно изобретаете существующие.NET SychronizationContext, как вид, используемый [этим кодом] (http://stackoverflow.com/a/21684059/17034). –

ответ

0

Если у вас есть свой собственный цикл сообщений, он должен быть захвачен в SynchronizationContext, поэтому, когда другой поток вызывает SynchronizationContext.Post - в этот Message Loop необходимо добавить действие обратного вызова.

СинхронизацияКонтекст «течет» как часть ExecutionContext, но не всегда, поэтому вам нужно позаботиться об этом потоке в коде (если это возможно).

Реализация по умолчанию метода Post является очередями действие на рабочий поток (получил с ILSpy):

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

Но большой вопрос, почему вам нужен собственный SynchronizationContext? Если это просто для удовольствия - все в порядке, иначе вы делаете что-то очень продвинутое, и, возможно, другие существующие более простые механизмы могут решить проблему.

Смежные вопросы