Как мне вызвать функцию потокобезопасным способом

#c# #.net-2.0

#c# #.net-2.0

Вопрос:

Я поиграл с методами безопасного вызова метода потокобезопасным способом в .net 2.0.

Мой treeview заполняется из вызова базы данных в отдельном потоке;

Ниже приведена моя попытка использовать мой метод InvokeFunction (показан ниже) … это работает, но я надеялся, что есть более приятный способ написать это … есть мысли по этому поводу?

 InvokeFunction(delegate() { TreeView1.Nodes.Clear(); });



delegate void FunctionDelegate();
private delegate void ThreadSafeProcess(FunctionDelegate func);
private void InvokeFunction(FunctionDelegate func)
{
  if (this.InvokeRequired)
  {
    ThreadSafeProcess d = new ThreadSafeProcess(InvokeFunction);
    this.Invoke(d, new object[] { func });
  }
  else
  {
    func();
  }
}
  

Комментарии:

1. Невозможно ответить на этот вопрос, если вы не расскажете больше о том, что делает ваша функция. Доступно много-много разных механизмов синхронизации, которые решают разные проблемы. Какой из них подходит, зависит от решаемой проблемы. В чем ваша проблема?

2. Дэвид, как ты можешь видеть, функция вызывает метод treeview clear nodes() для очистки узлов. Я просто поиграл с идеей создания чего-то более общего, чем явный вызов метода forms.control.

Ответ №1:

BackgroundWorker это более чистое решение в .NET 2.0. Это создаст для вас поток и позаботится о синхронизации.

Вы добавляете BackgroundWorker компонент в свою форму в режиме разработки. Вы подписываетесь на DoWork событие. Метод, подписанный на это, будет выполняться в фоновом потоке при вызове backgroundWorker.RunWorkerAsync() в вашем потоке пользовательского интерфейса.

Когда вам нужно взаимодействовать с потоком пользовательского интерфейса из вашего фонового потока, вы вызываете backgroundWorker.ReportProgress . Это вызовет ProgressChanged событие. ProgressChanged событие всегда выполняется в потоке пользовательского интерфейса. Вы можете использовать userState параметр backgroundWorker.ReportProgress для передачи любых данных в поток пользовательского интерфейса. Например, в вашем случае данные, необходимые для добавления новых TreeView узлов. Вы фактически добавите новые узлы внутри ProgressChanged обработчика событий.

Вот ссылка на MSDN:http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx .

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

Комментарии:

1. Я предполагаю, что это WinForms. Брэд сказал: «Мой treeview заполняется из вызова базы данных в отдельном потоке». К TreeView не должен быть доступ из любого другого потока, кроме потока пользовательского интерфейса. Итак, здесь требуется синхронизация потоков пользовательского интерфейса.

Ответ №2:

Вам не нужно беспокоиться о безопасности потоков, если вы не разделяете какое-либо состояние. Функции всегда получают свои параметры в стеке, а стек является локальным для каждого потока. Итак, функции — это не ваша проблема. Вместо этого сосредоточьтесь на состоянии. Объекты «treeView1» — это кандидат, о котором стоит беспокоиться.