Вызывающий поток не может получить доступ к этому объекту, потому что другой поток владеет им - PullRequest
0 голосов
/ 31 октября 2011

Я использую следующий код.

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 ]

2 голосов
/ 31 октября 2011

Только поток пользовательского интерфейса может получить доступ к элементам пользовательского интерфейса, что, как я догадываюсь, и есть эти txt вещи. Parallel.Invoke в вашем случае не является потоком пользовательского интерфейса, поэтому возникает исключение при попытке доступа к свойству .Text в элементах управления.

Вам необходимо перенаправить вызов в поток пользовательского интерфейса. В 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 модель аналогична, но включает Диспетчер:

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 голос
/ 31 октября 2011

Как сказал Адам, только поток пользовательского интерфейса может получить доступ к элементам пользовательского интерфейса.В случае WPF вы должны использовать myControl.Dispatcher.Invoke().

Так как все эти вызовы все равно будут вызываться в потоке пользовательского интерфейса, вы должны удалить Parallel.Invoke() и вызвать метод напрямую.

0 голосов
/ 31 октября 2011

Просто альтернативное предложение. Я хотел бы перейти к привязке данных к вашим текстовым полям к свойствам класса, даже если вы не хотите использовать полный дизайн MVVM, привязка данных - ваш друг в WPF. Затем, если вам нужна многопоточность, WPF будет обрабатывать элементы управления обновлением в потоке пользовательского интерфейса при изменении свойства, даже если свойство изменяется в другом потоке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...