Многопоточность Winforms: необходимо ли создавать новый делегат каждый раз при вызове метода в потоке пользовательского интерфейса? - PullRequest
5 голосов
/ 26 ноября 2010

Я хочу вызвать метод, который манипулирует элементом управления в потоке пользовательского интерфейса. Мой код работает, и я хочу оптимизировать. Я имею в виду этот ресурс на MSDN .
Согласно там, мы должны сделать

public delegate void myDelegate(int anInteger, string aString);
//...
Label1.Invoke(new myDelegate(myMethod), new Object[] {1, "This is the string"});

Будет ли при каждом вызове вводить объект-сироту (утечка памяти)?

Когда я делаю это со статическим экземпляром делегата, как показано ниже, а затем использую этот экземпляр при каждом вызове для вызова:

private static _delegateInstance = new myDelegate(myMethod);
//...
Label1.Invoke(_delegateInstance , new Object[] {1, "This is the string"});

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

Ответы [ 5 ]

2 голосов
/ 26 ноября 2010

Альтернативный «шаблон» (если его можно так назвать) состоит в том, чтобы метод просто вызывал себя, предполагая, что он является частью Form класса:

void myMethod(int anInteger, string aString)
{
    if (InvokeRequired)
    {
        Invoke(new Action<int,string>(myMethod),anInteger,aString);
        return;
    }

    Label1.Text = aString;
}

Объект Actionостанется в куче, измените текстовое свойство, затем GC'd при следующем сканировании.Я не вижу в этом снижения производительности, если метод не использует некоторые внешние ресурсы, такие как дескриптор IE, файл и т. Д.

2 голосов
/ 26 ноября 2010

Два ответа выше дали некоторое понимание. Вот хорошая статья здесь , если вы хотите получить более подробную информацию.

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

Кроме того, вы должны иметь в виду, что .Net обрабатывает поток пользовательского интерфейса немного по-другому. Если вы имеете дело с WPF, вам придется принять во внимание диспетчер. Смотри здесь .

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

Н.

1 голос
/ 26 ноября 2010

Будет ли при каждом вызове вводить объект-сироту (утечка памяти)?

Нет, не будет, все в порядке.

Но чтобыизбегайте создания делегата каждый раз, когда вы можете использовать некоторые из существующих (если ваш метод принимает 2 строковых параметра и не возвращает):

Label1.Invoke.Invoke((Action<string, string>)myMethod, 
    new object[] { 1, "This is the string" });
0 голосов
/ 13 октября 2012

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

Ваш второй фрагмент не создает объекты делегатов каждый раз, но это невозможно (при условии, что myMethod является экземпляромметод), поскольку статические члены не могут использовать члены экземпляра.

Дарин Димитров ошибается - его код использует существующий делегат Action вместо пользовательского, но он все равно создает объект делегата Action каждый раз (в отличие от вашего второго фрагмента),Итак, вы можете использовать следующий код:

private Action<int, string> _delegateInstance = myMethod;
//...
Label1.Invoke(_delegateInstance , new Object[] {1, "This is the string"});
0 голосов
/ 26 ноября 2010

Прежде всего, C # - это управляемый язык, следовательно, нет утечек памяти. Когда-либо.

Во-вторых, не принимайте MSDN в качестве окончательного решения, когда вы пытаетесь оптимизировать. Многие фрагменты кода, которые вы там найдете, даже не соответствуют собственным стандартам кодирования MS (даже самым базовым из них) или даже здравому смыслу.

В-третьих, строка: private _delegateInstance = new myDelegate (myMetho); не создает ничего статичного. Он создает переменную, которая содержит новый экземпляр, возвращенный из нового myDelegate (myMethod).

Наконец, использование ключевого слова «new» определенно будет создавать новый объект myDelegate при каждом вызове, а также поведение, совершенно отличное от написанного вами второго фрагмента кода, но в некоторых случаях это требуется.

Возможно, вы захотите использовать второй вариант, который вы написали, но настоящая правда в том, что вам следует потратить время и прочитать \ узнать больше о делегатах и ​​C # в целом.

Удачи и наслаждайтесь.

...