¿Cómo ejecutar algo en el hilo STA?

En mi aplicación WPF hago algunas comunicaciones asíncronas (con servidor). En la función de callback, termino creando objetos InkPresenter a partir del resultado del servidor. Esto requiere que el hilo en ejecución sea STA, que al parecer actualmente no lo es. Por lo tanto, recibo la siguiente excepción:

No se puede crear una instancia de ‘InkPresenter’ definida en el ensamblaje [..] El hilo de llamada debe ser STA, porque muchos componentes de la interfaz de usuario lo requieren.

Actualmente mi llamada de función asíncrona es así:

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

¿Cómo puedo hacer que la callback, que hará la creación de InkPresenter, sea STA? O invoque el análisis XamlReader en un nuevo hilo STA.

 public void SearchForFooCallbackMethod(IAsyncResult ar) { var foo = GetFooFromAsyncResult(ar); var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter; // <!-- Requires STA [..] } 

Puede iniciar los hilos STA de esta manera:

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

El único problema es que el objeto resultante debe pasarse de alguna manera. Puede usar un campo privado para eso, o sumergirse para pasar los parámetros a los hilos. ¡Aquí configuro los datos foo en un campo privado y comienzo el hilo STA para mutar el 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; } 

¡Espero que esto ayude!

Puede usar la clase Dipatcher para ejecutar la llamada al método en UI-Thread. El Dispatcher proporciona la propiedad estática CurrentDispatcher para obtener el despachador de un hilo.

Si su objeto de la clase, que crea el InkPresenter, se crea en el UI-Thread, entonces el método CurrentDispatcher devuelve el Dispatcher del UI-Thread.

En el Dispatcher puede llamar al método BeginInvoke para llamar al delegado especificado de forma asincrónica en el hilo.

Debería ser lo suficientemente bueno para llamarlo en el hilo de UI. Por lo tanto, use un BackgroundWorker y, en RunWorkerAsyncCompleted , puede hacer la creación de inkPresenter.

Es un truco, pero usaría XTATestRunner para que tu código se vea así:

  public void SearchForFooAsync(string searchString) { var caller = new Func(_patientProxy.SearchForFoo); caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null); } public void SearchForFooCallbackMethod(IAsyncResult ar) { var foo = GetFooFromAsyncResult(ar); InkPresenter inkPresenter; new XTATestRunner().RunSTA(() => { inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter; }); } 

como bonificación es posible detectar excepciones arrojadas en el hilo STA (o MTA) como este:

 try{ new XTATestRunner().RunSTA(() => { throw new InvalidOperationException(); }); } catch(InvalidOperationException ex){ }