2010-08-15 1 views
4

Довольно часто в моей GUI код, я пишу что-то вроде этого:Есть ли сокращенная версия Form.BeginInvoke?

private void SecondTimer_Elapsed(object sender, ElapsedEventArgs e) 
{ 
    if (progressBar1.InvokeRequired) 
    { 
     progressBar1.BeginInvoke(new ElapsedEventHandler(SecondTimer_Elapsed), new[] {sender, e}); 
     return; 
    } 
//Code goes here 
} 

Конечно, это необходимо, если приложение является многопоточной, так как нам нужно Маршаллу нить, первоначально созданный элемент управления. Дело в том, что может быть утомительно написать делегат и поместить аргументы в массив, и он занимает место в верхней части каждого такого обработчика событий. Есть ли какой-то атрибут или что-то в этом роде, которое заменит этот код для вас? В основном ярлык, в котором говорится: «Если вы ошибаетесь, вызовите меня снова в потоке графического интерфейса с теми же аргументами».

ответ

13

Я не знаю ничего подобного, но это, вероятно, будет полезным метод расширения для вас:

public static class Extensions 
{ 
    public static void Execute(this ISynchronizeInvoke invoker, 
           MethodInvoker action) 
    { 
     if (invoker.InvokeRequired) 
     { 
      invoker.BeginInvoke(action); 
     } 
     else 
     { 
      action(); 
     } 
    } 
} 

Сейчас это работает только для делегатов без параметров, конечно ... но с лямбда выражения, которые не должны быть проблемой:

progressBar1.Execute(() => SecondTimer_Elapsed(sender, e)); 

Это имеет следующие преимущества:

  • Это s реали написать
  • Вы не можете пойти неправильно с подписью (вы не полагаясь на позднее связывание)
  • MethodInvoker выполняется чуть более эффективно, чем другие делегаты, я считаю
  • Если у вас нет много код для выполнения, вы можете написать его inline в выражении лямбда
0

Захватите AOP framework для этого. Вы можете создать MethodInterceptionAspect, который срабатывает при вызове функции. Затем вы можете сделать проверки и либо бросить функцию (у вас есть ссылка на функцию и ее аргументы) в поток графического интерфейса, либо выполнить его напрямую.

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

+0

любой полный исходный код об этом? – Kiquenet

3

Вы можете привести в порядок это с методами расширения:

// Extension methods. 
public static void BeginInvoke(this ISynchronizeInvoke @this, MethodInvoker action) { 
    if (@this.InvokeRequired) @this.BeginInvoke(action); 
    else action(); 
} 

public static void BeginInvoke<T1, T2>(this ISynchronizeInvoke @this, Action<T1, T2> action, T1 arg1, T2 arg2) { 
    if (@this.InvokeRequired) @this.BeginInvoke(action, new object[] { arg1, arg2 }); 
    else action(arg1, arg2); 
} 

// Code elsewhere. 
progressBar1.BeginInvoke(() => SecondTimer_Elapsed(sender, e)); 
// Or: 
progressBar1.BeginInvoke(SecondTimer_Elapsed, sender, e); 

Edit: Джон Скит прав, говоря, что с помощью делегата MethodInvoker быстрее. Из MSDN:

Вызов к EventHandler или MethodInvoker делегат будет быстрее, чем вызов к другому типу делегата.