2013-12-21 2 views
1

У меня есть приложение, где я использую фоновый рабочий, чтобы начать какую-то последовательность. Иногда нужно обновлять графический интерфейс.BackgroundWorker, update gui, static method

У меня есть статический класс со ссылками на некоторые объекты gui. В моей логике я хочу вызвать метод из этого статического класса, с некоторыми параметрами, проанализировать его и обновить графический интерфейс. Но у меня есть "Вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит другой поток." exception.

установка переменной в первой теме:

public static void SetCardHand(ref CardHand ch) 
    { 
     cardHand = ch; 
    } 

метод вызывается из фона рабочего потока:

private static void SetCoveredCardsPlayer0(int cardsNumber) 
    { 

     if (cardsNumber < 1) 
      cardHand.imgCard1.Source = null; 
     else 
      cardHand.imgCard1.Source = (ImageSource)WindowManager.Instance.CardsGUI.CardsDictionary["T1"]; 
    } 

Как позволить этот GUI изменить метод?

Это не класс окон. Это что-то вроде ведущего.

Редакция2

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

+0

В зависимости от дизайна вашего приложения контур backgroundworker.WorkerReportsProgress = true и подписывается на ProgressChanged, который будет работать в потоке пользовательского интерфейса. – terrybozzio

+1

Вы должны указать *, где * вы вызываете SetCoveredCardsPlayer0. Это должно быть либо из обработчиков событий Completed или ProgressChanged - если это не так, вы получите это исключение. Посмотрите, что Grant опубликовал для ответа ниже, если вы делаете этот вызов над чем-то другим, кроме обработчиков событий Completed или ProgressChanged. –

ответ

5

Перед обновлением пользовательского интерфейса вы должны передать управление в основной поток. BackgroundWorker делает это довольно легко.

  1. При создании BackgroundWorker, установите WorkerReportsProgress = true.

  2. Подпишитесь на событие ProgressChanged и поместите свою логику, которая обновляет интерфейс пользователя в этом событии.

  3. В случае вашего события DoWork, если вы хотите обновить графический интерфейс, позвоните myBackgroundWorker.ReportProgress(0, someObject), где «someObject» - это часть данных, на которую вы хотите действовать. В вашем случае, возможно, ImageSource вы назначаете cardHand.imgCard1.Source.

  4. Внутри ReportProgress события, вы можете получить доступ к объекту, проходящему через e.UserState. Прежде чем использовать его, вы должны вернуть его обратно в ImageSource.

Вы можете сохранить if (cardsNumber < 1) логики внутри DoWork события, но если вы хотите установить Source Ань ImageSource (или null), вы хотите, чтобы передать это значение в ProgressChanged событие на самом деле обновить Элемент пользовательского интерфейса.

+0

Это довольно хорошо, но мне нужно несколько разных типов обновления. Как это можно сделать? – user1736332

+0

@ user1736332 Если вам нужно обновлять несколько элементов управления различными данными в разное время, пока поток работает, вам придется как-то разделить логику. Событие 'DoWork' может отправлять данные в событие' ProgressChanged', когда это необходимо, и тогда вы можете иметь логику в 'ProgressChanged', которая проверяет полученные данные и обновляет правильный элемент управления на основе этих данных. Или вы можете подождать, пока все закончите с событием DoWork, и передайте все данные в событие «RunWorkerCompleted» (используя «Tuple» или пользовательский класс) и просто обновите все компоненты пользовательского интерфейса оттуда. –