WPF/threading: Dispatcher static vs Dispatcher на элементе управления?

Я немного смущен с точки зрения диспетчера. Скажем, я нахожусь в фоновом потоке, выполняя какую-то длительную операцию. Я бы хотел обновить поток ui. Я понимаю, что делаю это через диспетчера. Мой вопрос в том, что я вызываю диспетчера статически, как: Dispatcher.BeginInvoke(mywork)... Или в элементе управления, который я хочу обновить: mytextbox.Dispatcher.BeginInvoke(mywork)

Ответ 1

Стоит отметить, что вызов Dispatcher.BeginInvoke не является статическим вызовом: он неявный this.Dispatcher.BeginInvoke. Если вы можете использовать этот вызов, скорее всего, вы будете писать свой код изнутри или из окна управления. В этом случае вы, вероятно, будете безопасны для звонков, так как большую часть времени будет один поток пользовательского интерфейса для каждого приложения.

Фактический статический вызов будет Dispatcher.CurrentDispatcher.BeginInvoke, который не является тем, что вы хотите вызвать (см. мой комментарий к Хасан-хану для ответа).

EDIT: Вызов Application.Current.Dispatcher - это не плохо. (И, для ясности, это свойство экземпляра, а не статическое - вызвано статическим/одиночным экземпляром Application.) Это свойство вернет Диспетчер для потока, с которым было создано приложение, и, как правило, поток что пользовательский интерфейс создается так же хорошо, поэтому Application.Current.Dispatcher возвращает тот же Диспетчер, что и myWindow.Dispatcher.

Статический вызов Dispatcher.CurrentDispatcher (который я предупреждал против) возвращает диспетчер для потока, из которого вы его вызываете. Если вы вызываете это из фонового потока, вы получите новый Диспетчер, созданный специально для этого потока, который часто не нужен.

Ответ 2

Сначала я думаю, что важно понять, что Dispatcher не предназначен для обработки больших фоновых операций. Он предназначен для работы в очереди на поток пользовательского интерфейса объекта. Вот заслуживающая внимания статья MSDN о модели потоковой передачи .NET и Dispatcher:

Говоря, что стандартным способом реализации метода Dispatcher.BeginInvoke было бы вызвать его на элементе управления:

startStopButton.Dispatcher.BeginInvoke(
    DispatcherPriority.Normal, new NextPrimeDelegate(CheckNextNumber)
);

Надеюсь, что это поможет!

Ответ 3

В большинстве случаев использование DispatcherObject.Dispatcher (все объекты зависимостей и элементы управления наследуются от DispatcherObject, среди прочих) или Application.Current.Dispatcher - это правильная вещь, так как обычно существует только один поток пользовательского интерфейса, может быть несколько В потоках пользовательского интерфейса и в разных окнах могут использоваться разные диспетчеры. В этом случае важно обновить элемент управления с помощью диспетчера. Он хранится в свойстве Dispatcher (унаследованном от DispatcherObject), любом другом элементе управления в этом окне и самом окне.