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

时间:2015-08-19 10:14:36

标签: c# multithreading dispatcher ui-thread

你可以在SO上找到很多类似的问题,但是当你的逻辑必须返回某些内容时,没有人(正如我所见)涵盖了情况。

在这个代码示例中,我有一个简单的CustomMessageBox(它是一个窗口),它必须返回由用户输入的内容。

public class CustomMessageBox  
{
  private string Value 
  {
      get 
      {
          return txt_box.Text;
      } 
  }

  private CustomMessageBox ()
  {
      InitializeComponent();
  }

  public static string Show(string caption = "Enter data")
  {
      CustomMessageBox cmb = new CustomMessageBox ();
      cmb.txt_block.Text = caption;

      cmb.ShowDialog();

      return cmb.Value;
  }
}

因此当Show调用BackgroundWorker方法时,第一行抛出异常,当构造函数尝试执行时。异常消息是

An exception of type 'System.InvalidOperationException' occurred in 
PresentationCore.dll but was not handled in user code


Additional information: The calling thread must be STA,  
because many UI components require this.

没什么新东西,但是我无法找到解决这个问题的方法,而且我不能让线程成为STA。 Show方法签名必须像这样清楚 - 取字符串并返回字符串。

通常这样的事情必须解决吗?

2 个答案:

答案 0 :(得分:1)

您无法从后台工作程序调用UI组件。这是您问题的直接原因。必须从UI线程创建所有UI组件并与之交互。这就是为什么我们在某些情况下有一些疯狂的逻辑来调用UI组件上的操作 - 在应用程序中只运行一个UI线程。

需要重新设计需要从后台进程填充UI元素的程序,以便将操作分成两个或更多个工作单元,从而消除了从后台操作UI的这一要求。

WPF and background worker and the calling thread must be STA

答案 1 :(得分:-1)

public static string Show(string caption = "Enter data")
{
    Application.Current.Dispatcher.Invoke(new Action(() =>
    {
        CustomMessageBox cmb = new CustomMessageBox();
        cmb.txt_block.Text = caption;
        cmb.ShowDialog();
    }));
    return cmb.Value;
}