簡體   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