MethodInvoker vs действие для контроля.BeginInvoke


что более правильно и почему?

Control.BeginInvoke(new Action(DoSomething), null);

private void DoSomething()
{
    MessageBox.Show("What a great post");
}

или

Control.BeginInvoke((MethodInvoker) delegate { 
    MessageBox.Show("What a great post");
}); 

Я вроде как чувствую, что я делаю то же самое, так что когда это подходящее время, чтобы использовать MethodInvoker vs Action, или даже писать лямбда-выражение?

EDIT: я знаю, что на самом деле нет большой разницы между написанием лямбда против Action, а MethodInvoker Кажется, сделано для определенной цели. Он делает что-то другое?

7 53

7 ответов:

оба одинаково верны, но документация для Control.Invoke гласит:

делегат может быть экземпляром EventHandler, в этом случае отправитель параметр будет содержать этот элемент, и параметр события будет содержать EventArgs.Пустой. Делегат также может быть экземпляром MethodInvoker, или любой другой делегат, который принимает пустоту список параметров. Вызов Делегат EventHandler или MethodInvoker будет быстрее, чем позвоните другому тип делегата.

Так MethodInvoker было бы более эффективным выбором.

для каждого решения ниже я запускаю 131072 (128*1024) итерации (в одном отдельном потоке). Помощник по производительности VS2010 дает следующие результаты:

  • только для чтения MethodInvoker: 5664.53 (+0%)
  • Новый MethodInvoker: 5828,31 (+2,89%)
  • функция cast In MethodInvoker: 5857.07 (+3.40%)
  • действие только для чтения: 6467.33 (+14.17%)
  • Новое Действие: 6829.07 (+20.56%)

вызов на новый действие на каждой итерации

    private void SetVisibleByNewAction()
    {
        if (InvokeRequired)
        {
            Invoke(new Action(SetVisibleByNewAction));
        }
        else
        {
            Visible = true;
        }
    }

вызов только для чтения, построить в конструкторе,действие на каждой итерации

    // private readonly Action _actionSetVisibleByAction
    // _actionSetVisibleByAction= SetVisibleByAction;
    private void SetVisibleByAction()
    {
        if (InvokeRequired)
        {
            Invoke(_actionSetVisibleByAction);
        }
        else
        {
            Visible = true;
        }
    }

вызов нового MethodInvoker на каждой итерации.

    private void SetVisibleByNewMethodInvoker()
    {
        if (InvokeRequired)
        {
            Invoke(new MethodInvoker(SetVisibleByNewMethodInvoker));
        }
        else
        {
            Visible = true;
        }
    }

вызов только для чтения, построить в конструкторе,MethodInvoker на каждой итерации

    // private readonly MethodInvoker _methodInvokerSetVisibleByMethodInvoker 
    // _methodInvokerSetVisibleByMethodInvoker = SetVisibleByMethodInvoker;
    private void SetVisibleByMethodInvoker()
    {
        if (InvokeRequired)
        {
            Invoke(_methodInvokerSetVisibleByMethodInvoker);
        }
        else
        {
            Visible = true;
        }
    }

вызов функции cast in MethodInvoker на каждой итерация

    private void SetVisibleByDelegate()
    {
        if (InvokeRequired)
        {
            Invoke((MethodInvoker) SetVisibleByDelegate);
        }
        else
        {
            Visible = true;
        }
    }

пример вызова решения "новое действие":

    private void ButtonNewActionOnClick(object sender, EventArgs e)
    {
        new Thread(TestNewAction).Start();
    }

    private void TestNewAction()
    {
        var watch = Stopwatch.StartNew();
        for (var i = 0; i < COUNT; i++)
        {
            SetVisibleByNewAction();
        }
        watch.Stop();
        Append("New Action: " + watch.ElapsedMilliseconds + "ms");
    }

Я предпочитаю использовать лямбды и действия / функции:

Control.BeginInvoke(new Action(() => MessageBox.Show("What a great post")));

действие определяется в системе, в то время как MethodInvoker определяется в системе.Окна.Формы-вам может быть лучше использовать действие, так как оно переносится в другие места. Вы также найдете больше мест, которые принимают действие в качестве параметра, чем MethodInvoker.

однако в документации указано, что вызовы делегатов типа EventHandler или MethodInvoker в элементе управления.Командлет Invoke() будет быстрее, чем любой другой тип.

кроме того, в каком namepsace они находятся, Я не знаю верьте, что есть смысл функциональное разница между действием и MethodInvoker-они по существу оба определены как:

public delegate void NoParamMethod();

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

также на MSDN:

MethodInvoker предоставляет простой делегат, который используется для вызова метода со списком параметров void. Этот делегат может использоваться при вызове метода Invoke элемента управления или когда вам нужен простой делегат, но вы не хотите его определять самостоятельно.

an действие С другой стороны, может занять до 4 параметров.

но я не думаю, что есть какая-то разница между MethodInvoker и действие поскольку они оба просто инкапсулируют делегат, который не принимает paremter и возвращает пустота

Если вы посмотрите на их определения, вы будете просто видеть.

public delegate void MethodInvoker();
public delegate void Action();

кстати, вы также можете написать свой второй строке.

Control.BeginInvoke(new MethodInvoker(DoSomething), null);

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

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

if(control.IsHandleCreated)
control.BeginInvoke((MethodInvoker)(() => control.Text="check123"));