Проблемы с доступом к компонентам графического интерфейса из другого потока.Диспетчер все еще выбрасывает исключение - PullRequest
0 голосов
/ 04 октября 2011

У меня есть окно, которое подписывается на событие, которое вызывается объектом. Я подписываюсь на событие следующим образом:

m_Monitor.NewJob += new Monitor.NewJobEvent(NewJobEventHandler);

Событие успешно создается и вызывает мой NewJobEventHandler. Проблема возникает, когда я пытаюсь внести изменения в любые элементы пользовательского интерфейса в окне. Я получаю следующее исключение:

System.Reflection.TargetInvocationException: {"Вызывающий поток не может получить доступ к этому объекту, потому что другой поток владеет им. "}

У меня была эта проблема раньше, и я использовал "Диспетчер" с некоторыми "Действие", чтобы обойти это. Я признаю, что все это кажется мне волшебным, и я действительно этого не понимал, но это помогло мне справиться с этой проблемой. Исходя из C ++ фона, я немного раздражен тем, что не могу получить доступ к определенным вещам, потому что они находятся в разных потоках. Но в любом случае моя процедура NewJobEventHandler () выглядит следующим образом:

private void NewJobEventHandler(JobInfo newJob)
{
    TreeViewItem tvItem = new TreeViewItem();
    tvItem.Header = "Job: " + newJob.ToString();

    //The following call is what causes the exception, yet I've used very
    //similar code to update the .Text property of a TextBox from another
    //thread
    OutputDataTree.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                (Action)(() => { OutputDataTree.Items.Add(tvItem); }));
}

Кто-нибудь знает, почему это не работает для меня?

1 Ответ

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

Вы создаете TreeViewItem в рабочем потоке, но используете его в потоке пользовательского интерфейса. Вам придется создать его в Action.

private void NewJobEventHandler(JobInfo newJob)
{
    TreeViewItem tvItem = new TreeViewItem();
    string header = "Job: " + newJob.ToString();

    //The following call is what causes the exception, yet I've used very
    //similar code to update the .Text property of a TextBox from another
    //thread
    OutputDataTree.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                (Action)(() => { 
                                  TreeViewItem tvItem = new TreeViewItem();
                                  tvItem.Header = header;
                                  OutputDataTree.Items.Add(tvItem); 
                               }));
}

Это относится к любому создаваемому вами элементу пользовательского интерфейса, его необходимо создать в потоке пользовательского интерфейса, чтобы его можно было использовать.

...