Наследование от DispatcherObject - PullRequest
       0

Наследование от DispatcherObject

1 голос
/ 02 декабря 2011

Я хотел бы создать подкласс DispatcherObject для создания своих собственных объектов, связанных с потоками, с очередью сообщений, как WPF использует для элементов пользовательского интерфейса.

У меня есть тестовое приложение, которое работает без сбоев,но DispatcherObject не обрабатывает свою очередь сообщений.Я только что создал новое пустое приложение WPF и добавил этот код в MainWindow.xaml.cs:

public partial class MainWindow : Window {
    public MainWindow() {
        InitializeComponent();

        DispatcherWorker worker = null;
        ManualResetEventSlim latch = new ManualResetEventSlim(false);

        new Thread(() => {
            worker = new DispatcherWorker();
            latch.Set();
        }).Start();

        latch.Wait();

        // worker.Dispatcher.Thread is stopped by here... why?
        worker.Dispatcher.BeginInvoke(new Action(() => {
            // This code never executed
            worker.DoWork(this);
        }));
    }
}

public class DispatcherWorker : DispatcherObject {

    public void DoWork(MainWindow window) {
        VerifyAccess();
        window.Dispatcher.BeginInvoke(new Action(() => window.Background = Brushes.Black));
    }
}

Метод DoWork() никогда не выполняется, и если я ставлю точку останова непосредственно перед вызовом BeginInvokeЯ вижу, что поток Диспетчера остановлен.Почему это остановлено?Я неправильно настраиваю поток?

( Похожий вопрос , похоже, имеет ту же проблему, но в принятом ответе говорится, что код запускается в приложении с графическим интерфейсом, в котором будет сообщениенасос. Но я получаю ту же проблему, даже когда работает в приложении с графическим интерфейсом.)

Ответы [ 3 ]

3 голосов
/ 03 декабря 2011

Нить, которой принадлежит Dispatcher, должна будет "накачать" эту Dispatcher.То есть ему нужно будет указать обработку сообщений, поставленных в очередь через этот Dispatcher.Для этого вы используете DispatcherFrame:

Dispatcher.PushFrame(new DispatcherFrame());

Это должно появиться после того, как вы установите защелку.Этот поток никогда не выйдет - он просто накачает сообщения в диспетчере этого потока.Если вы хотите, чтобы оно имело условие выхода, обратитесь к документации для свойства DispatcherFrame Continue.

Обратите внимание, что не имеет значения, используете ли вы свой пользовательский класс DispatcherWorkerили какой-то другой встроенный класс WPF.Если в этом потоке нет ничего Dispatcher, сообщения не будут обрабатываться.

1 голос
/ 02 декабря 2011

Я думаю, это потому, что worker.Dispatcher относится к потоку, в котором был создан DispatcherObject (в данном случае DispatcherWorker), который будет Thread, созданным в конструкторе.

Поскольку этот поток уже запущен и завершил свою работу, текущее состояние - Stopped.Возможно, вам придется запустить его снова, чтобы запустить DoWork()

Более подробную информацию по этому вопросу вы можете найти здесь

0 голосов
/ 18 октября 2015

Действительно, вы создали тему. И ваш DispatcherWorker создается в области созданного потока, который создает поток, который вы создали CurrentThread вашего DispatcherWorker.

Итак, в BeginInvoke случается, что DispatcherWorker прерывается, потому что PostMessage ("user32.dll") не перекачивает сообщение из вашего DispatcherWorker. Если ваш работник был создан вне области созданного потока, тогда все будет хорошо, потому что его диспетчер является главным диспетчером потока.

Таким образом, ваш работник заблокирован, потому что в BeginInvoke нет возможности перекачать сообщение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...