Reputation: 1011
I am using the following code.
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;
}
}
The program gives the following error
The calling thread cannot access this object because a different
thread owns it.
Which is the right way
update :
Whether this is right :
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;
}
}
Upvotes: 0
Views: 1990
Reputation: 119
Just an alternate suggestion. I would move toward databinding your textboxes to properties of a class, even if you don't want to go the full MVVM design, databinding is your friend in WPF. Then if you need the threading, WPF will handle updating controls on UI thread when the property changes, even when the property is changed on another thread.
Upvotes: 0
Reputation: 17648
As Adam said, only the UI thread can access UI elements. In the case of WPF, you'd use myControl.Dispatcher.Invoke()
.
Since these calls are all going to be invoked on the UI thread anyway, you should remove the Parallel.Invoke()
and call the method directly.
Upvotes: 1
Reputation: 64517
Only the UI thread can access UI elements, which I'm guessing is what those txt
things are. Parallel.Invoke
is in your case not the UI thread, so the exception is thrown when you try to access the .Text
property on the controls.
You need to marshal the call across to the UI thread. In WinForms, controls have various ways to help you do this:
if (myControl.InvokeRequired)
{
myControl.Invoke(...);
}
else
{
myControl.Text = "something";
}
MSDN has an article with examples on it here (VS2010):
http://msdn.microsoft.com/en-us/library/757y83z4(v=VS.100).aspx
Update 1:
For WPF the model is similar, but includes the Dispatcher:
myControl.Dispatcher.Invoke(...);
Update 2: Of course, it looks like you don't even need to use multi-threaded code here. I would guess the overhead of using the multi-threaded portion is more than the code you eventually call. Simply remove the use of multiple threads from this section and set the properties directly:
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;
}
Upvotes: 2