В моем приложении 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
[..]
}
Вы можете запускать потоки 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;
}
Надеюсь, это поможет!
Его должно быть достаточно, чтобы вызвать его в потоке пользовательского интерфейса. Поэтому используйте BackgroundWorker
и RunWorkerAsyncCompleted
, затем вы можете создать inkPresenter.
Вы можете использовать класс Dispatcher для выполнения вызова метода на UI-Thread. Диспетчер предоставляет статическое свойство CurrentDispatcher для получения диспетчера потока.
Если ваш объект класса, который создает InkPresenter, создан на UI-Thread, то метод CurrentDispatcher возвращает диспетчера UI-Thread.
На диспетчере можно вызвать метод BeginInvoke для асинхронного вызова указанного делегата на потоке.