Несоответствие количества параметров при вызове элемента управления с несколькими параметрами

Я использую поток для выполнения некоторого процесса на машине. В конце концов, о прогрессе сообщается в другом потоке. Чтобы обновить графический интерфейс со статусом процесса, я использую такой делегат:

public delegate void UpdateProgressDelegate(string description, int scriptnumber);
public void UpdateProgress(string description, int scriptnumber) {
    if (treeView.InvokeRequired) {
        treeView.Invoke(new UpdateProgressDelegate(UpdateProgress), description, scriptnumber);
        return;
    }
    // Update the treeview
}

И для вызова этого делегата я использую:

form.UpdateProgress("Ready", 3);

Когда вызывается Invoke, я получаю исключение TargetParameterCountException: несоответствие количества параметров. Я подумал, что смогу исправить это, поместив параметры string и int в один объект, например:

public delegate void UpdateProgressDelegate(object[] updateinfo);
public void UpdateProgress(object[] updateinfo) {
    string description = (string) updateinfo[0];
    int scriptnumber = (int) updateinfo[1];
    if (treeView.InvokeRequired) {
        treeView.Invoke(new UpdateProgressDelegate(UpdateProgress), new object[] { description, scriptnumber });
        return;
    }       
    // Update the treeview
}

И чтобы назвать это, я использую:

form.UpdateProgress(new object[] {"Ready", 3});

Но и это не работает. Я продолжаю получать одно и то же исключение TargetParameterCountException. Любые идеи, как я могу это исправить? Заранее спасибо!


person Carlito    schedule 19.01.2012    source источник
comment
Как объявляется метод AddScript? Или вы просто перепутали UpdateProgress с AddScript в приведенном выше коде?   -  person Thomas Levesque    schedule 19.01.2012
comment
@ThomasLevesque Упс, я их перепутал, AddScript — это совершенно другая функция! Я обновлю свой пост, проблема и исключение все те же.   -  person Carlito    schedule 19.01.2012
comment
@Tigran scriptnumber - целое число, я обновлю свой пост.   -  person Carlito    schedule 19.01.2012


Ответы (2)


Я бы сказал: сделайте это простым способом:

treeView.Invoke((MethodInvoker)delegate {
    UpdateProgress(description, scriptnumber);
});

или (равно):

treeView.Invoke((MethodInvoker) () => UpdateProgress(description, scriptnumber));

Это дает вам статическую проверку в компиляторе, а IIRC MethodInvoker проверяется явно и вызывается с Invoke(), а не DynamicInvoke(), что также делает его быстрее.


Почему это не работает; в вашем примере с:

public delegate void UpdateProgressDelegate(object[] updateinfo);

вы фактически передаете два параметра; чтобы устранить неоднозначность и передать один массив в params здесь, вам нужно дважды обернуть его:

treeView.Invoke(new UpdateProgressDelegate(UpdateProgress),
    new object[] { new object[] {description, scriptnumber }});

По сути, внешний массив — это «массив всех параметров», который содержит один элемент — массив, который мы не хотим передавать в качестве первого параметра (updateinfo).

person Marc Gravell    schedule 19.01.2012
comment
Ах вот почему! Но есть ли преимущество использования вашего решения вместо решения, которое дал Томас (с использованием функции делегата), кроме производительности? Или есть только два способа добиться одного и того же? - person Carlito; 19.01.2012
comment
@Carlito, если вы имеете в виду по сравнению с двойным переносом (т. Е. Битом внизу моего ответа) - это будет работать идентично более конкретному подходу делегирования; если вы имеете в виду по сравнению с анонимным методом (т.е. бит в верхней части моего ответа) - тогда: проверка статического типа в компиляторе! Это не позволит вам использовать недопустимые параметры и т. д. Это также позволяет избежать необходимости в запутанном дополнительном типе делегата. - person Marc Gravell; 19.01.2012
comment
Хорошо, спасибо, что помог мне. Я принял твой ответ! - person Carlito; 19.01.2012

Это должно работать:

public delegate void UpdateProgressDelegate(string description, int scriptnumber);
public void UpdateProgress(string description, int scriptnumber) {
    if (treeView.InvokeRequired) {
        treeView.Invoke(new UpdateProgressDelegate(UpdateProgress), new object[] { description, scriptnumber });
        return;
    }
    // Update the treeview
}
person Thomas Levesque    schedule 19.01.2012