调用线程无法访问此对象,因为另一个线程拥有它

时间:2011-10-31 11:27:41

标签: wpf c#-4.0 properties parallel-processing

我正在使用以下代码。

public partial class SettingApp
{
    public SettingApp()
    {
        InitializeComponent();
        Parallel.Invoke(SetDataInTextBox);
    }

    private void SetDataInTextBox()
    {
        txtIncAns.Text = Properties.Settings.Default.IncludeAN;
        txtIncAuthor.Text = Properties.Settings.Default.IncludeAutt;
        txtIncQuo.Text = Properties.Settings.Default.IncludeQU;
        txtIncSpBegin.Text = Properties.Settings.Default.IncludeSP;
    }
}

程序出现以下错误

  

调用线程无法访问此对象,因为其他

     

线程拥有它。

哪种方式正确

更新:

这是否正确:

   public partial class SettingApp
{
    private delegate void SetDataInTextBoxDelegate();
    public SettingApp()
    {
        InitializeComponent();

        txtIncAns.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new SetDataInTextBoxDelegate(SetDataInTextBox));
    }

     private void SetDataInTextBox()
    {
        txtIncAns.Text = Properties.Settings.Default.IncludeAN;
        txtIncAuthor.Text = Properties.Settings.Default.IncludeAutt;
        txtIncQuo.Text = Properties.Settings.Default.IncludeQU;
        txtIncSpBegin.Text = Properties.Settings.Default.IncludeSP;
    }
}

3 个答案:

答案 0 :(得分:2)

只有UI线程可以访问UI元素,我猜这些是txt事物。在您的情况下,Parallel.Invoke不是UI线程,因此当您尝试访问控件上的.Text属性时会抛出异常。

您需要将调用封送到UI线程。在WinForms中,控件有多种方法可以帮助您执行此操作:

if (myControl.InvokeRequired)
{
    myControl.Invoke(...);
}
else
{
    myControl.Text = "something";
}

MSDN上有一篇文章,其中有例子(VS2010):

http://msdn.microsoft.com/en-us/library/757y83z4(v=VS.100).aspx

更新1:

对于WPF,模型类似,但包括Dispatcher:

myControl.Dispatcher.Invoke(...);

更新2:当然,您甚至不需要在此处使用多线程代码。我猜想使用多线程部分的开销超过了你最终调用的代码。只需从本节中删除多个线程的使用并直接设置属性:

    public SettingApp()
    {
        InitializeComponent();
        SetDataInTextBox();
    }

    private void SetDataInTextBox()
    {
        txtIncAns.Text = Properties.Settings.Default.IncludeAN;
        txtIncAuthor.Text = Properties.Settings.Default.IncludeAutt;
        txtIncQuo.Text = Properties.Settings.Default.IncludeQU;
        txtIncSpBegin.Text = Properties.Settings.Default.IncludeSP;
    }

答案 1 :(得分:1)

正如Adam所说,只有UI线程可以访问UI元素。对于WPF,您可以使用myControl.Dispatcher.Invoke()

由于这些调用都是在UI线程上调用的,所以你应该删除Parallel.Invoke()并直接调用该方法。

答案 2 :(得分:0)

只是另一个建议。我会将文本框数据绑定到类的属性,即使你不想进行完整的MVVM设计,数据绑定也是你在WPF中的朋友。然后,如果您需要线程,WPF将在属性更改时处理UI线程上的更新控件,即使在另一个线程上更改了属性。