mrJack
mrJack

Reputation: 1011

The calling thread cannot access this object because a different thread owns it

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

Answers (3)

Brad
Brad

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

Daniel Rose
Daniel Rose

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

Adam Houldsworth
Adam Houldsworth

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

Related Questions