Поскольку Invoke/ BeginInvokeпринимает Delegate(а не типизированный делегат), вам необходимо сообщить компилятору, какой тип делегата нужно создать; MethodInvoker(2.0) или Action(3.5) - обычные варианты (обратите внимание, что у них одинаковая подпись); вот так:
(предостережение: вам нужно быть немного осторожным при использовании асинхронных захватов , но синхронизация в порядке - то есть вышеупомянутое в порядке)
Как я могу передать параметры вашему первому решению в этом ответе? Я имел в виду такое решение: control.Invoke ((MethodInvoker) delegate {this.Text = "Hi";});
uzay95
1
Почему вызывается метод расширения без явного приведения к действию?
P.Brian.Mackey
Поскольку компилятор может сделать это из использования.
RoboJ1M
1
Это то же самое, что уметь делать Form.Load += Loader()вместо старогоForm.Load += new EventHandler(Loader())
RoboJ1M
49
На самом деле вам не нужно использовать ключевое слово делегата. Просто передайте лямбда в качестве параметра:
Вам нужно создать тип делегата. Ключевое слово «делегат» при создании анонимного метода немного вводит в заблуждение. Вы создаете не анонимного делегата, а анонимный метод. Созданный вами метод можно использовать в делегате. Как это:
Для полноты картины это также можно сделать с помощью комбинации метода Action / анонимного метода:
//Process is a method, invoked as a method groupDispatcher.Current.BeginInvoke((Action)Process);//or use an anonymous methodDispatcher.Current.BeginInvoke((Action)delegate=>{SomeFunc();SomeOtherFunc();});
У меня были проблемы с другими предложениями, потому что я иногда хочу возвращать значения из моих методов. Если вы попытаетесь использовать MethodInvoker с возвращаемыми значениями, ему это не понравится. Итак, решение, которое я использую, похоже на это (очень рад услышать способ сделать это более лаконичным - я использую c # .net 2.0):
// Create delegates for the different return types needed.privatedelegatevoidVoidDelegate();privatedelegateBooleanReturnBooleanDelegate();privatedelegateHashtableReturnHashtableDelegate();// Now use the delegates and the delegate() keyword to create // an anonymous method as required// Here a case where there's no value returned:publicvoidSetTitle(string title){
myWindow.Invoke(newVoidDelegate(delegate(){
myWindow.Text= title;}));}// Here's an example of a value being returnedpublicHashtableCurrentlyLoadedDocs(){return(Hashtable)myWindow.Invoke(newReturnHashtableDelegate(delegate(){return myWindow.CurrentlyLoadedDocs;}));}
// Thread-safe update on a form controlpublicvoidDisplayResult(string text){if(txtResult.InvokeRequired){
txtResult.Invoke((Action)delegate{DisplayResult(text);});return;}
txtResult.Text+= text +"\r\n";}
Бонус: добавьте некоторую обработку ошибок, потому что, вероятно, если вы используете Control.Invokeиз фонового потока, вы обновляете текст / прогресс / состояние элемента управления и не заботитесь о том, что элемент управления уже удален.
Form.Load += Loader()
вместо старогоForm.Load += new EventHandler(Loader())
На самом деле вам не нужно использовать ключевое слово делегата. Просто передайте лямбда в качестве параметра:
источник
источник
Вам нужно создать тип делегата. Ключевое слово «делегат» при создании анонимного метода немного вводит в заблуждение. Вы создаете не анонимного делегата, а анонимный метод. Созданный вами метод можно использовать в делегате. Как это:
источник
Для полноты картины это также можно сделать с помощью комбинации метода Action / анонимного метода:
источник
Invoke((Action) Process);
лучший ответ, спасибо!У меня были проблемы с другими предложениями, потому что я иногда хочу возвращать значения из моих методов. Если вы попытаетесь использовать MethodInvoker с возвращаемыми значениями, ему это не понравится. Итак, решение, которое я использую, похоже на это (очень рад услышать способ сделать это более лаконичным - я использую c # .net 2.0):
источник
Мне нравится использовать Action вместо MethodInvoker, он короче и выглядит чище.
Например.
источник
Я никогда не понимал, почему это имеет значение для компилятора, но этого достаточно.
Бонус: добавьте некоторую обработку ошибок, потому что, вероятно, если вы используете
Control.Invoke
из фонового потока, вы обновляете текст / прогресс / состояние элемента управления и не заботитесь о том, что элемент управления уже удален.источник