MethodInvoker против действия для управления.Метод 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 ответов


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

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

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


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

  • только для чтения MethodInvoker: 5664.53 (+0%)
  • Нового Объекта Methodinvoker: 5828.31 (+2.89%)
  • функция приведенная в 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"));