简体   繁体   English

创建/添加新的wpf用户控件时,“调用线程必须是STA,因为许多UI组件都需要此”

[英]“The calling thread must be STA, because many UI components require this” while creating/adding new wpf usercontrol

I have a usertaskpane in VSTO add-in. 我在VSTO加载项中有一个usertaskpane。 I'm adding there winformshost and elementhost to be able to use wpf controls inside usertaskpane. 我在其中添加winformshost和elementhost以便能够在usertaskpane中使用wpf控件。

I managed to add a main wpf control, but I am failing with adding child user control to that. 我设法添加了一个主要的wpf控件,但是我未能在其中添加子用户控件。

I have such method that initiates adding new wpf control: 我有这样的方法可以启动添加新的wpf控件:

private void MasterCheck()
{
    this.pnlProgress.Visibility = System.Windows.Visibility.Visible;

    //I'm using progress bar functionality in ReturnMasters method
    Thread myNewThread = new Thread(() => Auditor.AuditMasterSlides(Globals.ThisAddIn.Application.ActivePresentation, this.pnlMaster, this, token));

    token = new CancellationTokenSource();
    myNewThread.Start();
    this.pnlProgress.Visibility = System.Windows.Visibility.Collapsed;
}

public static void AuditMasterSlides(PPT.Presentation pres, Panel panel, MainProofingTaskPaneControl control, CancellationTokenSource cancToken)
{
    IDictionary<string,MasterSlide> masterSlides = ReturnMasters(pres, cancToken, control);
    control.ShowAndCollapse(panel);
    control.RemovePanelChildren(panel);

    if (masterSlides.Count>1)
    {
        //control.AddControlToPanel(panel, new MasterCheckControlOK());
    }
    else
    {
        control.AddControlToPanel(panel, new MasterCheckControlOK());
    }
}

internal void RemovePanelChildren(Panel panel)
{
    this.Dispatcher.Invoke(() =>
    {
        for (int i = panel.Children.Count - 1; i >= 0; i--)
        {
            panel.Children.RemoveAt(i);
        }
    });
}

internal void AddControlToPanel(Panel panel, Control control)
{
    MasterCheckControlOK newControl = new MasterCheckControlOK();

    this.Dispatcher.Invoke(() =>
    {
        panel.Children.Add(newControl);
    });
}

And I'm getting error here: 而且我在这里出错:

public MasterCheckControlOK()
{
    InitializeComponent();
}

How can I solve it to be able to: 我该如何解决它才能:

  • use progress bar functionality (currently works) 使用进度条功能(当前有效)
  • add new wpf controls (does not work) 添加新的WPF控件(不起作用)
  • modify/remove controls (currently works) 修改/删除控件(当前有效)
  1. You can only create UI controls on STA (single-threaded apartment) threads: 您只能在STA(单线程单元)线程上创建UI控件:

The calling thread must be STA, because many UI components require this 调用线程必须是STA,因为许多UI组件都需要STA

  1. You can only access a control on the thread on which it was originally created. 您只能在最初创建控件的线程上访问控件。 For example, you cannot create a control on a thread B and then try to add it to the Children collection of a control that was created on thread A. 例如,您不能在线程B上创建控件,然后尝试将其添加到在线程A上创建的控件的Children集合中。

So it makes no sense to create a control on a background thread if you intend to interact with it one way or another from the main thread. 因此,如果您打算与主线程以一种或多种方式进行交互,则在后台线程上创建控件是没有意义的。 Then you will get this exception. 然后,您将获得此异常。

Bottom line: You should create all controls on the same thread and this thread should in most cases be the main UI/dispatcher thread. 底线:您应该在同一线程上创建所有控件,并且在大多数情况下,该线程应该是UI / dispatcher主线程。 This will save you a whole lot of trouble. 这将为您省去很多麻烦。

When you create a control it has to happen in the main UI thread. 创建控件时,它必须在主UI线程中发生。 Currently you are creating the control in another thread and then adding it to another. 当前,您正在另一个线程中创建控件,然后将其添加到另一个线程中。 This will cause an exception. 这将导致异常。

You need to move the creation of the control to happen inside the invoke so it happens on the main UI thread. 您需要将控件的创建移动到调用内部,以便控件发生在主UI线程上。

You can't create UI controls in separate threads. 您不能在单独的线程中创建UI控件。 The control needs to exist on the UI thread. 该控件需要存在于UI线程上。

You might try having your threaded function do its work through your window's Dispatcher using its .Invoke() methods. 您可以尝试使用其.Invoke()方法在窗口的Dispatcher .Invoke()线程函数完成其工作。

You probably want to make sure that ONLY the manipulation of your UI controls is done with the dispatcher otherwise you'll probably lock up the UI anyway. 您可能要确保通过分派器完成对UI控件的操作,否则可能仍会锁定UI。

public static void AuditMasterSlides(PPT.Presentation pres, Panel panel, MainProofingTaskPaneControl control, CancellationTokenSource cancToken)
{
    IDictionary<string,MasterSlide> masterSlides = ReturnMasters(pres, cancToken, control);

    this.Dispatcher.Invoke((() => control.ShowAndCollapse(panel));
    ...
}

As for the STA thread issue, you need to specify that your thread is an STA thread before you start it. 对于STA线程问题,您需要在启动之前指定您的线程是STA线程。

I did this by calling .SetApartmentState() on my thread: 我是通过在线程上调用.SetApartmentState()来完成此操作的:

thread1.SetApartmentState(ApartmentState.STA);
thread1.Start();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 调用线程必须是STA,因为许多UI组件在WPF中需要这个 - The calling thread must be STA, because many UI components require this in WPF InvalidOperationException:调用线程必须是STA,因为许多UI组件都需要STA - InvalidOperationException: The calling thread must be STA, because many UI components require this 调用线程必须是STA,因为许多UI组件在WPF中需要此错误。在form.show()上 - The calling thread must be STA, because many UI components require this error In WPF. On form.show() 调用线程必须是 STA,因为很多 UI 组件都需要这个,发生在 WPF 的 main 函数中 - The calling thread must be STA, because many UI components require this, happening in main function in WPF “调用线程必须是STA,因为许多UI组件都需要STA。” WPF - “The calling thread must be STA, because many UI components require this.” WPF 在SkypeKit.NET WPF应用程序中识别导致“调用线程必须是STA,因为许多UI组件需要此线程”的源线程时出现问题。 - Problems identifying source thread causing “The calling thread must be STA, because many UI components require this.” in SkypeKit.NET WPF Application 在DLL中创建位图时,发布的项目会产生错误“调用线程必须是STA,因为许多UI组件都需要此” - released project produces error “The calling thread must be STA, because many UI components require this” when creating bitmap in a DLL “调用线程必须是STA,因为许多UI组件都需要这个。”使用BeginInvoke动态添加ListView项时 - “The calling thread must be STA, because many UI components require this.” when adding ListView items dynamically using BeginInvoke 如果后台方法需要 UI,则任务不起作用:调用线程必须是 STA,因为许多 UI 组件需要此 - Task not working if background method needs UI: The calling thread must be STA, because many UI components require this "“调用线程必须是STA,因为许多UI组件都需要这个”单元测试期间的异常" - "The calling thread must be STA, because many UI components require this" exception during unit test
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM