外接程序中的 WPF 生命周期
我创建了一个外接程序,它通过 Reflection(一个 WPF 类库)进行调用。 由于这是一个类库,我必须手动实例化一个新的 System.Windows.Application()。
然后,类构造函数(通过反射调用的构造函数)创建一个窗口,并使用 Show()(使用 Dispatcher.Run() 以避免窗口立即关闭)或 ShowDialog()。
由于我的应用程序位于加载项中,因此应用程序仍然存在。 因此,我只能实例化一次。
首次启动时(实例化应用程序时),Application.Current.Dispatcher 正在运行。
但在第二次启动时,我确认 Application.Current.Dispatcher 已停止。 我从不调用 InvokeShutdown() 所以我不明白调度程序何时停止。
当我第二次启动它时,应用程序已经实例化(这是正常的),但调度程序停止了。
有什么想法吗? 谢谢 !
编辑:在我的外接程序中,我尝试了两种方法:
第一种方法:
foreach (Type type in ass2_l.GetTypes())
{
if (type.Name == "Loader")
{
object obj_l = Activator.CreateInstance(type);
BindingFlags bf_l = BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
object[] argList_l = new object[1];
argList_l[0] = "ok";
type.InvokeMember("Load", bf_l, null, obj_l, argList_l);
}
}
当我从外接程序直接调用 dll 时,Application.Current.Dispatcher 是处于后台状态,名称为“VSTA_Main”。 当我第二次启动时,Dispatcher 仍处于后台状态。
第二种方式:
t_m = new Thread(loadDll);
t_m.SetApartmentState(ApartmentState.STA);
t_m.Start();
loadDll 实际上包含与“第一种方式”代码相同的代码。 当我第一次启动此部分时,调度程序正在运行,一切都很正常。 第二次启动时,Dispatcher 停止。
编辑2: 问题出在第二种方式上。 当 loadDll 完成,然后我再次单击我的加载项按钮时,t_m 被停止,创建另一个并不能解决问题,因为 Dispatcher ManagedThreadId 具有旧的 t_m ManagerThreadId :/
编辑 3 : 该问题绝对不是由加载项引起的。 如果您只是创建一个程序,每次单击按钮时都会启动一个线程。 该线程尝试实例化 DLL WPF 类库(通过反射),如果您第二次单击此按钮(调用另一个线程),由于调度程序仍然“链接”到旧线程,因此调度程序将“停止” (就像旧线程一样)
I've created an add-in, which call via Reflection, a WPF Class Library.
Since this is a class library, I had to instanciate manually a new System.Windows.Application()
.
Then, the class constructor (the one called via reflection) create a window, and Show() (with Dispatcher.Run() to avoid the window to close immediately) or ShowDialog().
Since my application is into an add-in, Application is still alive.
Therefore, I can instanciate this only once.
On the first launch (when Application is instanciated), the Application.Current.Dispatcher is Running.
But on the second launch, I firured out that the Application.Current.Dispatcher was Stopped.
I never call InvokeShutdown() so I don't understand when the Dispatcher is stopped.
When I launch this a second time, Application is already instanciated (it's normal) but Dispatcher stopped.
Any idea ?
Thanks !
Edit : In my Add-in, I've tried 2 ways :
First way :
foreach (Type type in ass2_l.GetTypes())
{
if (type.Name == "Loader")
{
object obj_l = Activator.CreateInstance(type);
BindingFlags bf_l = BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
object[] argList_l = new object[1];
argList_l[0] = "ok";
type.InvokeMember("Load", bf_l, null, obj_l, argList_l);
}
}
When I call directly the dll from the add-in, Application.Current.Dispatcher is in Background State, with name "VSTA_Main".
When I launch a second time, Dispatcher is still in background state.
Second way :
t_m = new Thread(loadDll);
t_m.SetApartmentState(ApartmentState.STA);
t_m.Start();
loadDll actually contain the same code of the "first way" code.
When I launch this part for the first time, the Dispatcher is Running, and all is perfectly normal.
When launched the second time, Dispatcher is stopped.
EDIT 2 :
The problem is in the second way.
When loadDll is finished and then I click again on my add-in button, t_m is stopped and creating another one don't resolve the problem since the Dispatcher ManagedThreadId has the old t_m ManagerThreadId :/
EDIT 3 :
The problem is definately not caused by the Add-in.
If you Just create a program that launch a thread everytime you click on a button.
The thread try to instanciate a DLL WPF Class Library (by reflection), and if you click a second time on this button (calling another thread), as the Dispatcher is still "linked" to the old thread, the Dispatcher is "stopped" (like the old thread)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 ThisAddin.Startup 事件处理程序中放置以下代码:
这应该解决它,它过去对我来说工作得很好。
In ThisAddin.Startup event handler put this code:
That should sort it out, it has worked fine for me in the past..
最后,我使用无限循环解决了该问题,使线程保持在运行状态,并使用 AutoResetEvent / ManualResetEvent 来启动/停止线程...
因为线程永远不会完成(并调用一个在接收到消息时加载 WPF UI dll 的方法)启动事件),我们永远不会停止线程(直到我们停止外接程序),并且调度程序也永远不会停止。
顺便说一句,谢谢您的所有回答:)
Finally, I solved the problem using an infinite loop to stay the thread in running state, with AutoResetEvent / ManualResetEvent to start/stop the thread...
As the thread never finish (and call a method which load the WPF UI dll when he receive the start event), we never stop the thread (until we stop the Add-in), and the dispatcher is never stopped too.
BTW, thank you for all your answers :)