Необходим совет для стратегии многопоточности для приложения WPF - PullRequest
2 голосов
/ 27 августа 2009

Я создаю однооконное приложение WPF В окне есть список элементов (которые сохраняются в базе данных, конечно) Периодически мне нужно запускать фоновую задачу, которая обновляет базу данных из канала Atom. Когда каждый новый элемент добавляется в базу данных, список в пользовательском интерфейсе также должен обновляться, чтобы отразить это. Я не хочу, чтобы эта фоновая задача замедляла пользовательский интерфейс, но в то же время она должна взаимодействовать с пользовательским интерфейсом.

Прочитав множество статей и увидев множество простых примеров, я все еще не уверен, как лучше это реализовать.

То, что я думаю, возможно, я мог бы сделать:

В событии Window_Loaded создайте DispatchTimer. Когда происходит событие Tick, вызовите метод UpdateDb (). UpdateDB () получит элементы из ленты Atom и добавит их в базу данных. Когда я перебираю каждый элемент, я буду вызывать другой метод для повторного связывания списка с базой данных, чтобы он "обновлялся". Когда все задачи завершены, сбросьте DispatchTimer ??? (не уверен, что это можно / нужно / нужно сделать).

Помните, что это фоновая задача, поэтому пользователь может одновременно использовать пользовательский интерфейс.

Как это звучит?

Спасибо.

Ответы [ 4 ]

2 голосов
/ 27 августа 2009

Это звучит неоптимально, потому что вы подключаетесь к базе данных в потоке пользовательского интерфейса. Когда событие Tick запускается на DispatcherTimer, обработчики будут выполняться в потоке пользовательского интерфейса. Вам нужно минимизировать объем работы, выполняемой в этом потоке, чтобы поддерживать отзывчивость пользовательского интерфейса, и вам определенно не следует выполнять работу, связанную с IO, в этом потоке.

Возможно, у меня есть служба данных, в обязанности которой входит обновление базы данных и инициирование событий по мере внесения изменений. Ваш уровень пользовательского интерфейса может присоединиться к этим событиям и выполнить маршал в потоке пользовательского интерфейса для применения изменений. Чтобы выполнить маршалинг для потока пользовательского интерфейса, вам просто нужно позвонить Dispatcher.Invoke.

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

Еще одна вещь, на которую следует обратить внимание, это то, что WPF автоматически маршалирует для вас скалярные значения. Вам нужно только упорядочить изменения в коллекциях (добавление / удаление / замена элементов).

0 голосов
/ 28 августа 2009

Многопоточность WPF с BackgroundWorker . Автор Pavan Podila:

Хорошей новостью является то, что вам действительно не нужно писать такой компонент, поскольку он уже доступен: класс BackgroundWorker, представленный в .Net Framework 2.0. Программисты, знакомые с WinForms 2.0, возможно, уже использовали этот компонент. Но BackgroundWorker одинаково хорошо работает с WPF, потому что он абсолютно не зависит от модели потоков.

0 голосов
/ 28 августа 2009

Я бы использовал System.Threading.Timer, который будет вызывать указанный метод с заданным интервалом в потоке потоков, поэтому нет необходимости создавать дополнительный поток, сделайте вашу базу данных с этим и выполните маршал обратно в пользовательский интерфейс нить по мере необходимости.

0 голосов
/ 27 августа 2009

Ваш подход будет работать.

Вы запускаете таймер при загрузке приложения. Для каждого тика таймера вы запускаете поток для обновления базы данных. После обновления базы данных вы можете вызвать .BeginInvoke() для ваших объектов пользовательского интерфейса, чтобы обновить пользовательский интерфейс в потоке презентации (это будет единственный раз, когда ваш пользовательский интерфейс должен быть затронут).

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