没有表单的ActiveX控件
我们需要使用第三方ActiveX控件。
唯一的问题是,我们软件中的图层是业务层,无法访问窗口或表单。 它还运行在不是STA的单独线程上(并且应该可以在任何线程中工作)。
我们使用此解决方法使其工作,而不是将UI与业务逻辑分开。
Thread thread = new Thread((ThreadStart) delegate { _myActiveX = new MyActiveXType(); _myActiveX.CreateControl(); //more initialize work Application.Run(); }); thread.SetApartmentState(ApartmentState.STA); thread.IsBackground = true; thread.Start();
然后,只要我们需要引用控件,我们就会调用_myActiveX.BeginInvoke()
或Invoke()
。
在处理这个类(退出我们的应用程序)时,我们处理控件并中止线程。
我的问题是,这有什么问题吗? 有没有更好的方法来处理这个?
是否有更好的内置方法可以在未知的multithreading环境中使用ActiveX控件? 我们试图以包装控件的方式编写我们的类,但是可以在任何线程中工作。
更新:作为一个答案建议,我们真的宁愿使用标准的COM对象,而根本不使用控件。 我们的问题是我们会在我们调用COM对象的第一个方法或属性上得到错误“(来自HRESULT的exception:0x8000FFFF(E_UNEXPECTED)”。这是一个非常一般的错误,我们在使用ActiveX时没有得到这个错误, 有任何想法吗?
更新:我们的ocx是“CX25.ocx”,使用tlbimp.exe我们得到CX25Lib.dll。 使用aximp.exe,我们得到AxCX25Lib.dll和CX25Lib.dll。 在任何一种情况下CX25Lib.dll都不起作用。 AxCX25Lib.dll可以使用。
我认为这是解决这个问题的正确方法。
过去几周我们一直在测试环境中使用我的代码而没有任何问题。
如果有人必须使用没有表单的ActiveX,我认为这是一种方法。
只需确保在ActiveX对象的构造函数之后直接调用_yourActiveXControl.CreateControl()。 这简化了我们最初的许多问题。
如果从业务层调用ActiveX控件,这意味着它必须能够在没有UI的情况下使用,例如只需调用其公共方法即可。 为什么不直接为ActiveX控件类创建一个interop RCW并直接调用它的方法?
我的解决方案是创建一个托管activex控件的隐藏winform
我知道这是一个老post,但我建议在现代时代使用TPL。
由于围绕exception处理,取消,延续和返回结果的function,最好使用任务并行库而不是旧的线程API。
这是一个例子:
using (var sta = new StaTaskScheduler(1)) { var taskResult = await Task.Factory.StartNew(() => { var results = new List(); using (var ax = new MyActiveXType()) { // important to call this just after constructing ActiveX type ax.CreateControl(); ax.SomeIterativeEvent += (s, e) => results.Add(e.SomeThing); // if applicable, you can tear down the message pump ax.SomeFinalEvent += (s, e) => Application.ExitThread(); //more initialize work // start message pump Application.Run(); return results; } }, CancellationToken.None, TaskCreationOptions.None, sta); return taskResult; }
一些要点:
-
StaTaskScheduler
是在ParallelExtensionsExtras nuget包中找到的类型。 您需要这个来安排在单线程公寓中执行的任务。 -
我将1传递给
StaTaskScheduler
的构造函数,以便它只为我创建一个单独的线程。 -
调用
Application.ExitThread()
来停止消息泵,这反过来允许执行由Application.Run()
传递,以便可以将一些结果返回给调用者。