0

My previous question (SelectedIndex is unchanging in tabcontrol - Dispatcher issue) didn't get very far, and I suspect I was on the wrong track to begin with.

There are 3 givens in my program:

  1. I have a main window which is WPF.
  2. I connect to a separate application (a different process) which implements a COM server which can be called on at various times to perform time-consuming calculations, the results of which I will display in my window.
  3. I do not want the main window to freeze while waiting for these calculations to conclude. In fact, the operator should be free to continue using the program, though certain controls may be disabled pending conclusion of the asynchronous operation.

It seems to me that to achieve the above requirements that I need to have a separate thread dedictated to handling COM requests and that thread must be STA. Somehow I invoke this thread to do stuff, and somehow this thread invokes the GUI thread to update stuff. It's not clear to me technically how to make this happen.

Two questions: How do I implement these calls between threads? What's a clean architecture for this?

Community
  • 1
  • 1
Alan Baljeu
  • 2,383
  • 4
  • 25
  • 40
  • Check http://stackoverflow.com/questions/16738719/updating-ui-with-backgroundworker-in-wpf – Vojtěch Dohnal Dec 12 '14 at 13:55
  • Thanks for the link. I'm not clearly understanding what is presented there. – Alan Baljeu Dec 13 '14 at 03:20
  • @AlanBaljeu, maybe [this](http://stackoverflow.com/a/21357567/1768303) could help, if you're willing to use TPL and `async`/`await`. As to why using a `LocalServer32` out-of-proc COM object gives you *"this thread is not STA"*, perhaps you're also trying to handle any COM events sourced by that COM object? If so, check [this](http://stackoverflow.com/q/18458398/1768303). – noseratio Dec 14 '14 at 05:29
  • The problem appears to be gone now. I restructured the code so that it never saves handles to COM objects. The problem was connected to accessing these handles in different threads. There may be another approach, but not saving the objects but re-querying for them eliminates the issue. – Alan Baljeu Dec 15 '14 at 03:50

1 Answers1

0

Depending on your COM server you may use either an MTA or an STA threading model. The STA, Single Threaded Apartment is the simplest to use and the one I would recommend to begin with unless you are certain your COM supports MTA and you need to use MTA.

A safe way of calling long running COM objects is the following standard pattern: - From the UI thread start a new thread where your COM object will be called from. You can use a Task or a thread. Change the Thread Apartment to STA: System.Threading.Thread.CurrentThread.ApartmentState = ApartmentState.STA

  • Then from that thread you can instantiate and run your COM object as normal. When it has finished or when you get events from it that need to be passed on the main UI thread you raise an event from your code passing in the data (do not pass back the COM object, you need to decouple the data from it since it belongs to another thread) which your UI thread will intercept.

  • On your UI thread when you get back the event, you will need to use InvokeRequired / BeginInvoke if you use WinForm. I am not sure about WPF but I would expect you would need to synchronize the callback with the UI thread too.

  • The server I'm using requires STA. I also need objects (at minimum, the server object) to persist through many calls from the UI. How do I work with a persistent thread? Also, is async/await part of this? – Alan Baljeu Dec 12 '14 at 13:47
  • Just create a normal thread for your COM and use the lock keyword when calling it from the ui thread to synchronize the two threads when needed. There is nothing much different than if it was a normal non COM object. – Michael Moreno Dec 12 '14 at 14:17
  • I'm completely new at this. I don't know how to even make a thread run certain code. – Alan Baljeu Dec 12 '14 at 21:35