繁体   English   中英

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

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

我在VSTO加载项中有一个usertaskpane。 我在其中添加winformshost和elementhost以便能够在usertaskpane中使用wpf控件。

我设法添加了一个主要的wpf控件,但是我未能在其中添加子用户控件。

我有这样的方法可以启动添加新的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);
    });
}

而且我在这里出错:

public MasterCheckControlOK()
{
    InitializeComponent();
}

我该如何解决它才能:

  • 使用进度条功能(当前有效)
  • 添加新的WPF控件(不起作用)
  • 修改/删除控件(当前有效)
  1. 您只能在STA(单线程单元)线程上创建UI控件:

调用线程必须是STA,因为许多UI组件都需要STA

  1. 您只能在最初创建控件的线程上访问控件。 例如,您不能在线程B上创建控件,然后尝试将其添加到在线程A上创建的控件的Children集合中。

因此,如果您打算与主线程以一种或多种方式进行交互,则在后台线程上创建控件是没有意义的。 然后,您将获得此异常。

底线:您应该在同一线程上创建所有控件,并且在大多数情况下,该线程应该是UI / dispatcher主线程。 这将为您省去很多麻烦。

创建控件时,它必须在主UI线程中发生。 当前,您正在另一个线程中创建控件,然后将其添加到另一个线程中。 这将导致异常。

您需要将控件的创建移动到调用内部,以便控件发生在主UI线程上。

您不能在单独的线程中创建UI控件。 该控件需要存在于UI线程上。

您可以尝试使用其.Invoke()方法在窗口的Dispatcher .Invoke()线程函数完成其工作。

您可能要确保通过分派器完成对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));
    ...
}

对于STA线程问题,您需要在启动之前指定您的线程是STA线程。

我是通过在线程上调用.SetApartmentState()来完成此操作的:

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

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM