我正在编写一个WPF应用程序,该应用程序具有对具有简单要求的API的可选依赖性;它必须在没有STAThread属性的线程上初始化/使用。当然,WPF需要STA才能让一切变得简单。
在这种情况下,无论如何都需要WPF。仅当用户选择在应用程序中启用此功能时,才需要此第三方API。这意味着一旦调用其他API,WPF应用程序就已经在运行。
如果不使用[STAThread]装饰主方法,它是否自动成为MTA线程?在这种情况下,这是否意味着我可以创建一个新的MTA线程并使用其他API?
如果这样可行,那么我猜这个API中的任何事件都可以使用Dispatcher与WPF应用程序通信(用于引发需要在UI中显示的事件等)。但是,有一种简单的方法可以让我的WPF应用程序在MTA线程上“调用”功能来进行API调用吗?
在MTA中我猜每个线程应该能够使用状态,但我想我的STA线程(WPF应用程序)不能只是“进入”MTA线程并执行API调用?
这里有很多混淆的可能性,我会喜欢关于如何设计这样的东西的一些意见!
谢谢!
[编辑7月8日]
哦,我在上面有一些概念混淆了。线程模型当然是为PROCESS设置的,而不是为每个线程设置的,这个第三方API不能与STA进程一起使用。目前,我从这个混乱中看到的唯一方法是编写与此API通信的服务,然后使用命名管道与此服务进行通信。这根本不是一件小事,一个丑陋丑陋的解决方法,但第三方API不在我的控制之下。这就是人生。 :|
答案 0 :(得分:6)
外部API是GUI API吗?或者只是功能等?如果是后者,则可以生成第二个线程(可能使用生产者/消费者队列),即MTA:
Thread thread = new Thread(DoSomeStuff);
thread.SetApartmentState(ApartmentState.MTA);
thread.Name = "3rd aprty API spooler";
thread.Start();
答案 1 :(得分:3)
您需要启动一个新线程来调用需要MTA线程的代码。 你可以尝试类似下面的内容,以便在mta线程上轻松调用。这将在MTA线程执行时阻止主线程。这有多高将取决于您的API使用情况,因为每次调用它时都会启动一个新线程。
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();
}
}
然后你应该能够将你的api称为
MtaHelper.RuntMta( () => OtherAPIMethod() );
答案 2 :(得分:2)
我在WPF中利用了DispatcherObject。
我创建了DispatcherObject的子类,然后使用MTA线程创建一个实例。这样,我可以使用mySubclass.Invoke(...)或mySubclass.BeginInvoke(...),执行代码将在我的MTA线程上发生。
你可以在这里看到一个例子:
http://wpfmediakit.codeplex.com/SourceControl/changeset/view/24019#283908
特别注意CreateDvdPlayer静态方法,并查看BaseClasses.cs中的基类