2010-03-17 2 views
0

Я читал много о потоковом в C#, WPF и Silverlight, но не могу заставить его работать.Простая Threading в WPF

Основная проблема заключается в том, что у меня есть _load (_Initialized) действие, и у него много создания объекта, и вместе с тем у меня есть таймеры, работающие с разными вещами, это заставляет время запуска программы быть очень медленным и, очевидно, заставляет пользовательский интерфейс зависать, и это не очень удобно для развертывания для многих пользователей.

Мои таймеры изменяют значения меток и текстовых полей, но если они делают это в другом потоке, это очевидно.

Так может ли кто-нибудь дать мне несколько примеров того, как добиться того, что мне нужно делать?

Благодаря

ответ

1

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

Во-первых, вы должны объявить делегат, который можно подать методу Dispatcher.Invoke:

private delegate void UIDelegate(); 

Тогда вы можете получить настройки фона и уборщица назвать это RunWorkerAsync метод:

BackgroundWorker loadWorker = new BackgroundWorker(); 
loadWorker.DoWork += new DoWorkEventHandler(loadWorker_DoWork); 
loadWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(loadWorker_RunWorkerCompleted); 
loadWorker.RunWorkerAsync(); 

Затем, чтобы обновить элементы пользовательского интерфейса, вы должны вызвать их диспетчеру:

private void changeStatusLabel(string status) 
{ 
    progressLabel.Dispatcher.Invoke(new UIDelegate(delegate 
    { 
     progressLabel.Content = status; 
    })); 
} 

Они вырезаны из более крупных методов, и они могут быть оптимизированы немного. Тем не менее, это даст вам место для начала.

+0

Спасибо за всю информацию, я попробовал, но что входит в loadWorker_DoWork()? что, если у меня есть метка, которая выглядит так: this.label.Content = getCurrentUsage(). ToString(); Как я могу поместить все в то, как это будет в таймере. –

+0

LoadWorker_DoWork точно так же, как и ваше событие таймера, и вам нужно будет использовать Dispatcher.Invoke для обновления пользовательского интерфейса. –

+0

Или вы можете использовать делегат отчета о ходе выполнения BackgroundWorker, который работает в потоке пользовательского интерфейса только для этой цели. –

2

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

Это, если можно, вы также можете реорганизовать свою работу, чтобы использовать BackgroundWorker class. События прогресса и завершения уже привязаны к потоку пользовательского интерфейса, поэтому упрощается обновление пользовательского интерфейса во многих ситуациях.

+0

Ahem. Я думаю, вы имели в виду диспетчера. Откат, если вы не согласны. –

+2

@ Хенк: Любой может быть использован. Я часто использую BeginInvoke вместо Invoke, если я просто устанавливаю метки или другие подобные вещи, так как нет причин ждать завершения операции. - http://msdn.microsoft.com/en-us/library/ms591206.aspx –

+0

Да, моя ошибка. В последнее время я видел несколько делегатов.BeginInvokes в подобных ответах. –