我正在使用以下代码。
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;
}
}
答案 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线程上的更新控件,即使在另一个线程上更改了属性。