Я интерпретирую ваш вопрос так, как будто вы используете класс BackgroundWorker
для многопоточной работы. Тогда тогда возникает вопрос, как сообщения попадают в коллекцию GlobalVariables.MessageList
. Если это происходит в событии RunWorkerCompleted
, у вас не должно быть проблем с многопоточностью, поскольку он выполняется в потоке пользовательского интерфейса (именно так я и рекомендую). Если он обновляется непосредственно из рабочего процесса, вам необходимо самостоятельно позаботиться о проблемах синхронизации и потоков (используя один из доступных механизмов блокировки).
Обновление (после ответа на комментарий в исходном вопросе):
RunWorkerCompleted обычно должен выполняться в потоке пользовательского интерфейса (или, скорее, скорее в потоке, в котором был вызван RunWorkerAsync, я полагаю), поэтому вам обычно не нужно беспокоиться о проблемах с потоками при обновлении пользовательского интерфейса из этого потока. Однако, чтобы быть уверенным, вы можете использовать следующий подход:
private void BackgroundWorker_RunWorkerCompleted(object sender,
System.ComponentModel.RunWorkerCompletedEventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(
new Action<object, RunWorkerCompletedEventArgs>(
BackgroundWorker_RunWorkerCompleted), sender, e);
}
else
{
// update the message list, and then call SetMessages()
SetMessages();
}
}
Тем не менее, я призываю вас точно определить, при каких обстоятельствах возникает исключение из потоков, поскольку оно не должно происходить при использовании события RunWorkerCompleted
. Я провел тест, в котором одновременно запустил большое количество (несколько сотен) фоновых рабочих и не смог спровоцировать какого-либо столкновения. Он также не использовал Invoke-path в приведенном выше примере кода.
В качестве дополнительного примечания я думаю, что вам не нужно было бы сначала сохранять сообщения в списке, просто очистить и заново заполнить текстовое поле всеми сообщениями каждый раз. Я думаю, что вместо этого вы можете изменить метод SetMessages на метод, который принимает сообщение в качестве параметра и просто добавляет сообщение в текстовое поле:
private void SetMessage(MyMessage message)
{
var text = message.Date.ToShortTimeString() + " " + message.Label + ": " + message.TheMessage;
switch (message.Type)
{
case GlobalVariables.MessageType.normal:
rtxtMessage.SelectionColor = Color.Black;
break;
case GlobalVariables.MessageType.calculation:
rtxtMessage.SelectionColor = Color.Green;
break;
case GlobalVariables.MessageType.error:
rtxtMessage.SelectionColor = Color.Red;
break;
case GlobalVariables.MessageType.warning:
rtxtMessage.SelectionColor = Color.Orange;
break;
default:
break;
}
rtxtMessage.SelectedText = text + Environment.NewLine;
rtxtMessage.ScrollToCaret();
pnlMessage.Visible = true;
}
Вы должны иметь возможность вызывать этот метод прямо из обработчика событий RunWorkerCompleted и просто передавать сообщение в метод.