2013-03-17 4 views
1

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

Ошибка

The calling thread must be STA, because many UI components require this. 

Вот как я передаю контроль браузера в мой класс фон одноплодной.

public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      brwser.Navigate("https://xyz.com"); 
     } 

     private void Button_Click_1(object sender, RoutedEventArgs e) 
     { 
      Task.Factory.StartNew(() => 
      { 
       if (BfScrapper.Instance.CanStart) 
        BfScrapper.Instance.StartTask(brwser); 
      }); 
     } 
    } 
+0

Не повторяйте теги в заголовках. –

+0

его пример дублирования повторения не использует Task/Task Factory Class для запуска нового экземпляра одноэлементного класса –

+0

Я отредактировал ваш заголовок. Пожалуйста, смотрите: «Если вопросы включают« теги »в их названиях?] (Http://meta.stackexchange.com/questions/19190/), где консенсус« нет, они не должны ». –

ответ

2

Вам нужно будет запустить задачу, в которой работает поток STA.

Для этого вам нужно будет использовать TaskScheduler.FromCurrentSynchronizationContext (предполагая, что нить, из которой вы создаете задачу, сама является потоком STA).

Вы можете передать это в одну из перегрузок TaskFactory.StartNew, которая принимает аргумент TaskScheduler.

Например:

Task.Factory.StartNew 
(
    () => 
    { 
     if (BfScrapper.Instance.CanStart) 
      BfScrapper.Instance.StartTask(brwser); 
    }, 
    CancellationToken.None, 
    TaskCreationOptions.None, 
    TaskScheduler.FromCurrentSynchronizationContext() 
); 

Я также рекомендую вам Google FromCurrentSynchronizationContext STA, так как этот материал далеко не очевидно, и имеет последствия.

+0

можете ли вы поделиться фрагментом кода, как использовать в этом случае, передавая contorl? –

+0

Огромное спасибо, что я мог бы дать много очков, а не как других людей, которые решают старые ответы, это тот ответ, который я хотел услышать от такого эксперта, как вы. Поскольку этот класс использует Task Factory –

+1

Когда я впервые начал использовать Задачи вместо Threads, я столкнулся с этой проблемой (это было легко исправить для потоков, потому что вы можете просто установить состояние STA для потока). Мне потребовалось довольно много времени, чтобы узнать о функции FromCurrentSynchronizationContext()! Но будьте честны для всех - они все пытаются помочь (и я сам часто публикую ответы, которые, оказывается, не так полезны, как я надеялся ...) –

1

Я думаю, вы пытаетесь что-то изменить в переданном элементе пользовательского интерфейса. Самый простой способ сделать это так:

UIElement.Dispatcher.BeginInvoke(/*do stuff here*/);

У меня есть удобный метод расширения для этого:

public static DispatcherOperation DispatcherCall<T>(this T obj, Action action, DispatcherPriority priority) where T : DispatcherObject 
     { 
      return obj.Dispatcher.BeginInvoke(priority, action); 
     } 

использование будет выглядеть следующим образом:

mLabel.DispatcherCall(() => mLabel.Text = "Test...", DispatcherPriority.Normal); 

Этот избегает довольно большой стоимости всегда необходимости переключаться между контекстами синхронизации

Смежные вопросы