Как я могу создать средства управления WPF в фоновом потоке?

У меня есть метод, которые создают фоновый поток для создания некоторого действия. В этом фоновом потоке я создаю объект. Но этот объект при создании во времени выполнения дает мне исключение:

Вызывающим потоком должен быть STA, потому что много компонентов UI требуют этого.

Я знаю, что должен использовать Диспетчера для создания, отражают что-то к UI. Но в этом случае я просто создаю объект и не делаю iteract с UI. Это - мой код:

    public void SomeMethod()
      {
         BackgroundWorker worker = new BackgroundWorker();
         worker.DoWork += new DoWorkEventHandler(Background_Method);
         worker.RunWorkerAsync();
      }

   void Background_Method(object sender, DoWorkEventArgs e)
      {
         TreeView tv = new TreeView();
      }

Как я могу создать объекты в фоновом потоке?

Я использую приложение WPF

10
задан Factor Mystic 31 March 2012 в 19:40
поделиться

7 ответов

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

Что вы хотите сделать, так это проделать всю трудоемкую работу в фоновом потоке, а затем «перезвонить» потоку пользовательского интерфейса для управления пользовательским интерфейсом. На самом деле это довольно просто:

void Background_Method(object sender, DoWorkEventArgs e)
{
    // ... time consuming stuff...

    // call back to the window to do the UI-manipulation
    this.BeginInvoke(new MethodInvoker(delegate {
        TreeView tv = new TreeView();
        // etc, manipulate
    }));
}

Возможно, я ошибся в синтаксисе для BeginInvoke (это не в моей голове), но все равно что ...

6
ответ дан 4 December 2019 в 01:00
поделиться

Чтобы ваш код просто работал, вы должны присоединиться к квартире STA COM , позвонив по телефону Thread.SetApartmentState (ApartmentState.STA) . Поскольку BackgroundWorker , вероятно, использует какой-то общий пул потоков, присоединение к конкретному апартаменту может повлиять на других пользователей этого пула потоков или даже может завершиться ошибкой, если он уже был установлен, например, MTA ранее. Даже если все сработает, ваш вновь созданный TreeView будет заблокирован для этого рабочего потока. Вы не сможете использовать его в своем основном потоке пользовательского интерфейса.

Если вы немного подробнее объясните свои истинные намерения, вам наверняка помогут.

0
ответ дан 4 December 2019 в 01:00
поделиться

Попробуйте ввести код:

public void SomeMethod() 
{ 

System.ComponentModel.BackgroundWorker myWorker = new  System.ComponentModel.BackgroundWorker();

myWorker.DoWork += myWorker_DoWork;

myWorker.RunWorkerAsync();

}

private void myWorker_DoWork(object sender,
   System.ComponentModel.DoWorkEventArgs e)
{
   // Do time-consuming work here
}
0
ответ дан 4 December 2019 в 01:00
поделиться

См. Ответ на этот вопрос: Как запустить что-то в потоке STA?

Когда вы определяете свой поток, установите для параметра ApartmentState значение STA:

thread.SetApartmentState(ApartmentState.STA);

Это должно помочь !

0
ответ дан 4 December 2019 в 01:00
поделиться

Я решил свою проблему. Я просто использовал свойство e.Result метода RunWorkerCompleted. Я получаю данные в фоновом потоке, а затем использую эти данные, когда поток завершается. Спасибо всем за полезные методы. Особая благодарность Виру за рекомендацию по свойству e.Result .

0
ответ дан 4 December 2019 в 01:00
поделиться

HTH:

    void Background_Method(object sender, DoWorkEventArgs e)
    {
        // Time Consuming operations without using UI elements
        // Result of timeconsuming operations
        var result = new object();
        App.Current.Dispatcher.Invoke(new Action<object>((res) =>
            {
                // Working with UI
                TreeView tv = new TreeView();
            }), result);
    }
3
ответ дан 4 December 2019 в 01:00
поделиться
void Background_Method(object sender, DoWorkEventArgs e) 
{ 
    TreeView tv = new TreeView(); 
    // Generate your TreeView here
    UIDispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => 
    { 
        someContainer.Children.Add(tv);
    }; 
}
0
ответ дан 4 December 2019 в 01:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: