Понимание очереди диспетчера
Я думаю, что мне нужна помощь в понимании очереди диспетчера.
Когда приходит новая работа, она добавляется в начало очереди диспетчера, а когда диспетчер хочет обработать рабочий элемент, он удаляется с самого начала.
В более общем плане: если есть работа, она хранится в очереди в виде FIFO и обрабатывается до тех пор, пока не осталось работы.
Документация MSDN здесь относится к loop
и frame
:
The Dispatcher processes the work item queue in a loop. The loop is referred to as a frame.
Но где петля в этом контексте? Для меня цикл - это то, что повторяет что-то, и когда он достигает конца, он начинается снова.
И какова концепция frame
? Согласно документации MSDN, фрейм - это удар рабочих элементов в очереди? Если это правда, как статический метод Disptatcher.PushFrame()
использоваться?
И самый интересный вопрос - есть ли какой-нибудь способ получить текущее состояние очереди, особенно, сколько элементов в очереди.
Придерживается ли выполнение метода, который был вызван ранее (и, следовательно, помещен в очередь Dispatcher), что он сразу же удаляется из очереди или он сохраняется внутри в течение другого периода времени?
Я знаю, так много вопросов:-)
1 ответ
Там очень мало документации, связанной с Dispatcher
так что вам придется немного разобраться, чтобы узнать о внутренней работе.
Диспетчер - это в основном то, что выполняет работу вокруг Message Pumps приложения. Этот вопрос находится в верхней части цикла сообщений Windows.
Как следствие, может быть только одно приложение Dispatcher - глобальный объект диспетчера, доступный для Application.Current.Dispatcher
, Другие диспетчеры возможны путем доступа Dispatcher.CurrentDispatcher
который согласно документации
Получает диспетчер для потока, выполняемого в данный момент, и создает новый диспетчер, если он еще не связан с потоком.
Тем не менее, призывая Run
на этом новый диспетчер будет блокировать.
Когда вы делаете Dispatcher.PushFrame
, это в основном помещает кадр в текущий диспетчер. Все, что наследуется от DispatcherObject
такие как DispatcherFrame
его диспетчер будет установлен на текущий. Мы можем убедиться в этом, посмотрев на его конструктор.
private Dispatcher _dispatcher;
protected DispatcherObject()
{
this._dispatcher = Dispatcher.CurrentDispatcher;
}
Конечно, простого цикла обработки событий недостаточно - бывают случаи, когда вам необходимо подорвать текущий цикл обработки событий, чтобы выполнить другую работу. И вот почему у вас есть DispatcherFrame
, Это то, что фактически составляет цикл обработки событий. Когда вы вставляете фрейм в Диспетчер, вот что происходит:
while (frame.Continue)
{
if (!this.GetMessage(ref msg, IntPtr.Zero, 0, 0))
{
break;
}
this.TranslateAndDispatchMessage(ref msg);
}
Это в TranslateAndDispatchMessage
что приоритетная очередь в Dispatcher будет оценена после удаления сообщения.
Если операции, выполняемой диспетчером, требуется много времени, она временно останавливает цикл обработки событий, и, поскольку она не отвечает на сигналы, приложение перестает отвечать на запросы.
Вот статья, которая использует фрейм, чтобы заставить пользовательский интерфейс реагировать, позволяя в ближайшее время запустить цикл обработки событий.
Что касается доступа к очереди, то как она есть, нет способа узнать состояние очереди за пределами диспетчера. Это внутренняя деталь, и разумно, что она не разоблачена.