Как отлаживать исключения Cross-Thread в .NET? - PullRequest
3 голосов
/ 20 февраля 2010

Я тестировал программу, которую пишу, и получил это сообщение об ошибке: Cross-thread operation not valid: Control 'lblStatus' accessed from a thread other than the thread it was created on

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

Я не использую явно «многопоточность».Я предполагаю, что что-то другое автоматически создает несколько потоков - я использую библиотеку удаленного аппаратного доступа Wii и выполняю графические манипуляции.

Трассировка стека показывает, что сделан вызов обработчику события при изменениикоторая вызывает функцию, в которой lblStatus пытается измениться, но не удается.

Мне было интересно, как вы отлаживаете эти типы ошибок.Я использую Visual Studio 2008.

РЕДАКТИРОВАТЬ

Одна вещь, которую я хочу уточнить, я не знаю, как этот другой поток даже возник.Как бы я нашел это?источник другой ветки.

Ответы [ 4 ]

4 голосов
/ 20 февраля 2010
public void SetStatus(string msg)
{
    if (lblStatus.InvokeRequired)
        lblStatus.Invoke(new MethodInvoker(delegate
        {
            lblStatus.Text = msg;
        }));
    else
        lblStatus.Text = msg;
}

Это обновит текст вашего ярлыка.

Для BeginInvoke я знаю это (я знаю, что есть более элегантные реализации) - но я еще не пробовал это в многопоточном приложении:

Action<string> setStatus= target.AppendText;

void OnSomeEvent (object sender, EventArgs e)
{ 
    IAsyncRes iares = setStatus.BeginInvoke("status message", null, null); 
    setStatus.EndInvoke(iares);
}

public void SetStatus(string msg)
{ lblStatus.Text = msg; }

Для различных методов синхронизации с потоком управления SnOrfus ссылается на отличную ссылку. Мой пример выше для BeginInvoke: не правильно для синхронизации с потоком элемента управления.

Что касается того, что вызывает поток: О событии WiimoteChanged

2 голосов
/ 20 февраля 2010

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

Пример:

this.Dispatcher.Invoke((Action)(() => lblStatus.Content = "Hello"));

или (без лямбды):

this.Dispatcher.Invoke((Action)delegate() { lblStatus.Content = "Hello"; });
0 голосов
/ 20 февраля 2010

Одна вещь, которую я хочу уточнить, я не знаю, как эта другая тема даже возникла

Если ваше приложение не является многопоточным, проблема может быть вызвана процессом размещения Visual Studio. Процесс размещения Visual Studio запускает основной поток, а затем создает новый поток пользовательского интерфейса, в котором запускается приложение. В некоторых случаях это может привести к исключению между потоками, например при доступе к Form.ActiveForm перед вызовом Application.Run .

Если это ваша проблема, вы можете снять флажок «Включить процесс размещения Visual Studio» на вкладке «Отладка» свойств проекта.

0 голосов
/ 20 февраля 2010

Вам необходимо объединить использование Делегатов с вашими темами.

Назначьте ваш метод делегату, а затем вызовите делегат через поток.

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