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

时间:2012-05-24 07:27:29

标签: c# wpf sta apartment-state

我正在使用WPF Toolkit提供的MessageBox。我收到了错误

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

new Thread(new ThreadStart(delegate
{
    MessageBox.Show("Opeartion could not be completed. Please try again.","Error",MessageBoxButton.OK,MessageBoxImage.Error);
})).Start();

如何在这种情况下设置ApartmentState

编辑: 我试图使用WPF Toolkit的MessageBox控件显示无模式MessageBox。 到目前为止,我的代码如下:

void SomeFunction()
{
// calls to some UI, and processing and then

var th = new Thread(new ThreadStart(delegate
                                        {
                                           MessageBox.Show("Opeartion could not be completed. Please try again.",
                                                "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                                        }));

                                        th.SetApartmentState(ApartmentState.STA);
                                        th.Start();
                                    }
}

3 个答案:

答案 0 :(得分:4)

与用户界面的框架一样,与许多Windows窗体一样,WPF也强制使用单个线程模型,这意味着您只能访问创建它的指定派生DispatcherObject线程。在实现接口ISynchronizeInvoke的Windows窗体控件中,此接口公开一组方法(如Invoke和BeginInvoke)以强制执行合约公共线程同步,我们可以使用该同步从另一个线程访问控件。在WPF中,我们也有这样的东西,但这些操作都涉及一个名为Dispatcher的类,Dispatcher WPF是允许这种线程同步模型的方式。

以下是调用者位于不同线程时如何修改TextBox.Text属性的示例:

// Resets textbox text from another thread
textBox.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() =>
{
    textBox.Text = "New text";
}));

答案 1 :(得分:0)

<强> EDITED

根据MSDN在WPF中存在内置模式MessageBox但如果要使用无模式MessageBox,则必须创建自定义窗口然后显示它。 从自定义无模式MessageBox创建,显示和返回值并不是很难。 您可以看到this链接

仅对消息框使用不同的线程并不明智。无论如何,你可以通过以下方式设置单一的公寓状态......

  Thread th = new Thread(new ThreadStart(delegate
  {
    MessageBox.Show("Opeartion could not be completed. Please try again.", "Error",MessageBoxButtons.OK,MessageBoxImage.Error);
  }));

  th.ApartmentState = ApartmentState.STA;
  th.Start();

答案 2 :(得分:0)

// enable unit test to mock a dispatcher
var dispatcher = Dispatcher.CurrentDispatcher;
if (Application.Current != null)
{
    // use the application dispatcher if running from the software
    dispatcher = Application.Current.Dispatcher;
}

if (dispatcher != null)
{
    // delegate the operation to UI thread.
    dispatcher.Invoke(
        delegate
        {
            MessageBox.Show("Opeartion could not be completed. Please try again.","Error",MessageBoxButton.OK,MessageBoxImage.Error);
        });
}