Как выполнить что-то в потоке STA?

В моем приложении WPF я делаю некоторую асинхронную коммуникацию (с сервером). В функции обратного вызова я заканчиваю тем, что создал объекты InkPresenter из результата сервера. Это требует, чтобы рабочий поток был STA, который, по-видимому, это в настоящее время не. Поэтому я получаю следующее исключение:

Не может создать экземпляр 'InkPresenter', определенного в блоке [..] Вызывающий поток должен быть STA, потому что много компонентов UI требуют этого.

В настоящее время мой асинхронный вызов функции похож на это:

public void SearchForFooAsync(string searchString)
{
    var caller = new Func<string, Foo>(_patientProxy.SearchForFoo);
    caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null);
}

Как я могу сделать обратный вызов - который сделает создание InkPresenter - быть STA? Или вызовите парсинг XamlReader в новом потоке STA.

public void SearchForFooCallbackMethod(IAsyncResult ar)
{
    var foo = GetFooFromAsyncResult(ar); 
    var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter; // <!-- Requires STA
    [..]
}
38
задан stiank81 4 March 2010 в 09:15
поделиться

3 ответа

Вы можете запускать потоки STA следующим образом:

    Thread thread = new Thread(MethodWhichRequiresSTA);
    thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
    thread.Start(); 
    thread.Join(); //Wait for the thread to end

Единственная проблема в том, что ваш объект результата должен быть каким-то образом передан ... Вы можете использовать для этого частное поле или погрузиться в передачу параметров в потоки. Здесь я устанавливаю данные foo в частное поле и запускаю поток STA, чтобы изменить inkpresenter!

private var foo;
public void SearchForFooCallbackMethod(IAsyncResult ar)
{
    foo = GetFooFromAsyncResult(ar); 
    Thread thread = new Thread(ProcessInkPresenter);
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    thread.Join(); 
}

private void ProcessInkPresenter()
{
    var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter;
}

Надеюсь, это поможет!

58
ответ дан 27 November 2019 в 03:31
поделиться

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

3
ответ дан 27 November 2019 в 03:31
поделиться

Вы можете использовать класс Dispatcher для выполнения вызова метода на UI-Thread. Диспетчер предоставляет статическое свойство CurrentDispatcher для получения диспетчера потока.

Если ваш объект класса, который создает InkPresenter, создан на UI-Thread, то метод CurrentDispatcher возвращает диспетчера UI-Thread.

На диспетчере можно вызвать метод BeginInvoke для асинхронного вызова указанного делегата на потоке.

11
ответ дан 27 November 2019 в 03:31
поделиться
Другие вопросы по тегам:

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