void itemCommand_Click(Office.CommandBarButton Ctrl, ref bool CancelDefault)
{
var thread = new Thread(() =>
{
if (LoginCheck())
{
ItemWindow itw = new ItemWindow();
//Dispatcher.CurrentDispatcher.Invoke((System.Action)(() =>
//{
itw.Show();
itw.Closed += (sender2, e2) => { itw.Dispatcher.InvokeShutdown(); };
//}));
Dispatcher.Run();
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
我不断收到错误消息“调用线程无法访问此对象,因为另一个线程拥有它。”在线“itw.show();”当这个函数调用两次时。它适用于第一次调用,在窗口关闭并尝试再次打开后,它会失败。当我注释掉“Invoke”方法时,它也不适用于Dispatcher。请帮我找到解决方案。 谢谢。
-----------------编辑
我创建新主题的原因是因为它是一个Excel插件。如果我从主线程创建它,我无法从主线程创建窗口,这是与窗口碰撞的excel 我不明白的是,为什么新线程中的新实例(ItemWindow)与旧线程冲突。
答案 0 :(得分:0)
我在新应用程序中创建了一个简单的测试方法,当我单击主窗体上的(仅)按钮时调用该方法。该方法如下所示:
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread thread = new Thread(() =>
{
Window1 window = new Window1();
window.Closed += (s, a) => window.Dispatcher.InvokeShutdown();
window.Show();
System.Windows.Threading.Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
Window1
是我制作的一个窗口类,它上面只有一个TextBlock
。我可以根据需要多次单击该按钮,并且它会继续打开没有问题的新窗口(无论我是否先关闭前一个窗口)。
我怀疑代码中出现的问题是您没有向我们展示某个地方。您需要非常小心,新线程上的任何内容都不会尝试访问与主线程相关的任何UI。在不同线程上运行的Windows除非通过另一个线程的调度程序,否则无法相互通信。当从创建该对象的线程以外的线程访问DispatcherObject的任何方法或属性时,抛出您看到的异常。
退一步,为什么新窗口在自己的线程上很重要?除非新窗口将独占线程,否则它可能在主线程上正常运行。如果您正在运行一些长时间阻塞操作,那么单独该操作可能应该移动到一个线程而不是整个窗口。我不知道你在做什么,但这是值得考虑的事情。
编辑:意识到您可能没有在典型的WPF应用程序中运行(看起来您可能在Office插件中),我更新了我的测试以在他们自己的线程上完全独立地启动Windows。但是,我仍然能够连续启动两个窗口而没有任何问题。
这是我的新测试。此方法和测试类Window1
是我的整个应用程序。
[STAThread]
public static int Main(string[] args)
{
ThreadStart threadFunc = () =>
{
Window1 window = new Window1();
window.Closed += (s, a) => window.Dispatcher.InvokeShutdown();
window.Show();
System.Windows.Threading.Dispatcher.Run();
};
Thread thread = new Thread(threadFunc);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
thread = new Thread(threadFunc);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
return 0;
}
因此,您尝试执行的操作似乎没有任何内在错误,也不会在您的代码中看到任何明显的问题。我怀疑在显示时,自定义窗口中某处发生了一些无效的跨线程通信。 (或者,您遇到了Office插件特有的问题。)
答案 1 :(得分:0)
您正尝试将事件处理程序连接到ItemWindow 之后它已经可见。
您需要从以下地址切换订单:
ItemWindow itw = new ItemWindow();
itw.Show();
itw.Closed += (sender2, e2) => { itw.Dispatcher.InvokeShutdown(); };
到
ItemWindow itw = new ItemWindow();
itw.Closed += (sender2, e2) => { itw.Dispatcher.InvokeShutdown(); };
itw.Show();
答案 2 :(得分:-1)
可能的原因是依赖属性。在涉及线程时,依赖属性有点挑剔。
即使您没有定义自己的DepProps,您的窗口仍会有一些,并且无法摆脱它们。
DepProps有一个明显的缺点:它们是线程绑定的,无法从另一个线程访问。哪个线程拥有所有权限由初始化DepProps的线程定义,在您的情况下是第一次调用new ItemWindow()
。在第一次调用之后,您的线程被设置,您需要该线程来访问您的DepProps。
对于第一个没有问题的窗口,但第二个窗口显然有不同的线程。我不确切知道DepProps是如何做到这一点的,但您可能会尝试捕获并恢复第一个线程的同步上下文。另一种选择是捕获第一个线程(而不是主线程)的调度程序