C# 文本框自定义上下文菜单样式错误,多线程错误

C# 文本框自定义上下文菜单样式错误,多线程错误,c#,wpf,multithreading,textbox,C#,Wpf,Multithreading,Textbox,在WPF应用程序中,我使用自定义样式的文本框,其中ContextMenu被覆盖,如下所示: <Style TargetType="{x:Type TextBox}"> <Setter Property="ContextMenu"> <ContextMenu> <MenuItem Header="Copy"/> </ContextMenu> </Setter> &

在WPF应用程序中,我使用自定义样式的文本框,其中ContextMenu被覆盖,如下所示:

  <Style TargetType="{x:Type TextBox}">
    <Setter Property="ContextMenu">
      <ContextMenu>
        <MenuItem Header="Copy"/>
      </ContextMenu>
    </Setter>
  </Style>
Thread thread = new Thread(()=>
                                {
                                TestWindow wnd = new TestWindow();
                                wnd.ShowDialog();
                                });
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
但这会导致InvalidOperationException“调用线程无法访问此对象,因为另一个线程拥有它。”


如何避免此问题?

在您的代码中,您希望在非UI线程中修改UI,这是不允许的

应用UI更新时,您必须确保自己处于UI线程上。您可以通过检查
object.invokererequired
的值来检查这是否是必需的。如果需要,可以通过调用
object.invoke([delegate])
来调用该方法


此外,还可以使用dispatcher,请参见和。快乐阅读

问题在于您的样式被重用为优化,因此上下文菜单被重用-这是标准的,适用于单线程,但不适用于多线程

我会尝试将样式移动到resourcedictionary并将其引用为StaticResource,然后用以下标记: x:Shared=“false” 这将在每次访问资源时创建一个新实例-我不确定它是否适用于您所拥有的“一网打尽”无键样式。
然后,您可以将contextmenu设置为一个资源,并将其引用为StaticResource—这应该可以做到。

另一个解决方案是使用eventsetter进行右键单击并动态创建contextmenu。