Using WPF (which requires STAThread) with an API that cannot work with STAThread

I am writing a WPF application that has an optional API dependency that has a simple requirement; It MUST be initialized / used in a thread that does NOT have the STAThread attribute. Of course, WPF requires an STA to keep things simple.

In this case, WPF is required no matter what. This third-party API is only required when the user decides to include this feature in the application. This means that the WPF application is already running as soon as it's time to reference another API.

If you do not decorate your main method with [STAThread], is this an automatic MTA thread? In this case, does this mean that I can create a new MTA thread and use a different API on it?

If this works, I think that any events from this API could talk to the WPF application using the Dispatcher (to raise events that need to be shown in the user interface, etc.). However, is there a simple way in which my WPF application can “call” functions in the MTA thread to call the API?

In MTA, I assume that each thread should be able to play with state, but I think that my STA thread (WPF application) cannot just “reach” the MTA thread and make API calls?

There is so much room for confusion that it will be very useful for me how to create something like that!

Thanks!

[Edit, July 8th]

Okey, I had some concepts confusing above. The streaming model, of course, is set for PROCESS, and not for each stream, and this third-party API cannot work with the STA process.

Currently, the only way to avoid this mess is to write a service that communicates with this API, and then communicate with this service using named pipes. This is not at all trivial, an ugly ugly workaround, but a third-party API is not under my control. Such is life .: |

+4
source share
3 answers

Is the external API a GUI API? Or just functions, etc.? If the latter, then you can create a second thread (possibly using the producer / consumer queue), which is the MTA:

Thread thread = new Thread(DoSomeStuff); thread.SetApartmentState(ApartmentState.MTA); thread.Name = "3rd aprty API spooler"; thread.Start(); 
+5
source

You will need to create a new thread to invoke your code, which requires an MTA stream. You can try something like the following so that it is easy to call in the mta stream. This blocks the main thread while the MTA thread is running. How effective this will be depends on your use of the API when you deploy a new thread each time you call it.

 public delegate void MtaMethod(); public class MtaHelper { public static void RunMta(MtaMethod method) { ManualResetEvent evnt = new ManualResetEvent(false); Thread thread = new Thread(delegate() { method(); evnt.Set(); }); thread.SetApartmentState(ApartmentState.MTA); thread.Start(); evnt.WaitOne(); } } 

and then you can call your api like

 MtaHelper.RuntMta( () => OtherAPIMethod() ); 
+3
source

I am using DispatcherObject in WPF.

I subclass DispatcherObject and then instantiate using the MTA thread. That way I can use mySubclass.Invoke (...) or mySubclass.BeginInvoke (...), and the executable code will happen in my MTA stream.

Here you can see an example:

http://wpfmediakit.codeplex.com/SourceControl/changeset/view/24019#283908

Pay particular attention to the static CreateDvdPlayer method, and also look at the base class in BaseClasses.cs

+2
source

Source: https://habr.com/ru/post/1286611/


All Articles