воскресенье, 19 июня 2011 г.

Работа и решение проблем при роботе с виндовс формс(Win Forms) при обращении из фонового потока. Шаблоны обращения к форме.

Довольно хорошо всем известна проблема возникающая при попытке обращения к свойствам или методам виндовс формы, WPF формы. Также известно что эта проблема решается с помощью применения маршализацыи.

Пример кода для работы с виндовс формой из фонового потока:

   1: Action action = delegate()
   2:     {
   3: // код работы с формой и её контролами 
   4:         label1.Text =
   5:             DateTime.Now.ToLongTimeString();
   6:     };
   7: // проверка нужно ли исполнять код с помощью маршализации или нет,
   8: //есле нужно применяем маршализацыю.
   9:     if (this.InvokeRequired)
  10:         this.Invoke(action);
  11:     else
  12:         action();

Аналогичный пример для WPF:



   1: Action action = () => textBlock1.Text =
   2:         DateTime.Now.ToString();
   3:     if (System.Threading.Thread.CurrentThread !=
   4:         textBlock1.Dispatcher.Thread)
   5:     {
   6:         textBlock1.Dispatcher.Invoke
   7:             (System.Windows.Threading.DispatcherPriority.Normal,
   8:             action);
   9:     }
  10:     else
  11:     {
  12:         action();
  13:     }

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


Метод расширения для класса Control для роботы из фонового потока.



   1: public static class ControlExtensions
   2: {
   3:     public static void InvokeIfNeeded(this Control ctl,
   4:         Action doit)
   5:     {
   6:         if (ctl.InvokeRequired)
   7:             ctl.Invoke(doit);
   8:         else
   9:             doit();
  10:     }
  11:  
  12:     public static void InvokeIfNeeded<T>(this Control ctl,
  13:         Action<T> doit, T args)
  14:     {
  15:         if (ctl.InvokeRequired)
  16:             ctl.Invoke(doit, args);
  17:         else
  18:             doit(args);
  19:     }
  20: }

Метод расширения контрола для работы из фонового потока совместимый с C# 2.0



   1: public delegate void Action;
   2: public delegate void Action<T>(T arg);
   3:  
   4: public static class ControlExtensions
   5: {
   6:     public static void InvokeIfNeeded(Control ctl, Action doit)
   7:     {
   8:         if (ctl.InvokeRequired)
   9:             ctl.Invoke(doit);
  10:         else
  11:             doit();
  12:     }
  13:  
  14:     public static void InvokeIfNeeded<T>( Control ctl,
  15:         Action<T> doit, T args)
  16:     {
  17:         if (ctl.InvokeRequired)
  18:             ctl.Invoke(doit, args);
  19:         else
  20:             doit(args);
  21:     }
  22: }

Пример использования


С# 2.0



   1: private void OnTick20(object sender, EventArgs e)
   2: {
   3:     ControlExtensions.InvokeIfNeeded(this, delegate()
   4:     {
   5:         toolStripStatusLabel1.Text =
   6:           DateTime.Now.ToLongTimeString();
   7:     });
   8: }

С# 3.5



   1: this.InvokeIfNeeded(() => toolStripStatusLabel1.Text =
   2:         DateTime.Now.ToLongTimeString());

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

Отправить комментарий