Анонимный метод как параметр для BeginInvoke?
Почему вы не можете передать анонимный метод в качестве параметра методу BeginInvoke
? У меня есть следующий код:
private delegate void CfgMnMnuDlg(DIServer svr);
private void ConfigureMainMenu(DIServer server,)
{
MenuStrip mnMnu = PresenterView.MainMenu;
if (mnMnu.InvokeRequired)
{
mnMnu.BeginInvoke((CfgMnMnuDlg)ConfigureMainMenu,
new object[] { server});
}
else
{
// Do actual work here
}
}
Я пытаюсь избежать объявления делегата. Почему я не могу написать что-то вроде ниже? Или я могу, и я просто не могу понять правильный синтаксис? Ниже в настоящее время создается:
Тип аргумента "Анонимный метод" не присваивается типу параметра "System.Delegate"
Хорошо, это право, конечно, но есть ли другой синтаксис, который я могу использовать для этого (не нужно объявлять отдельный делегат, чтобы использовать BeginInvoke()
?
(Возможность сделать это вписывается в концепцию использования методов anon/lamdas вместо явных делегатов, которые работают так чисто везде).
private void ConfigureMainMenu(DIServer server,)
{
MenuStrip mnMnu = PresenterView.MainMenu;
if (mnMnu.InvokeRequired)
{
mnMnu.BeginInvoke( // pass anonymous method instead ?
delegate(DIServer svr) { ConfigureMainMenu(server);},
new object[] { server});
}
else
{
// Do actual work here
}
}
Ответы
Ответ 1
Попробуйте следующее:
control.BeginInvoke((MethodInvoker) delegate { /* method details */ });
Или:
private void ConfigureMainMenu(DIServer server)
{
if (control.InvokeRequired)
{
control.BeginInvoke(new Action<DIServer >(ConfigureMainMenu), server);
}
else
{
/* do work */
}
}
Или:
private void ConfigureMainMenu(DIServer server)
{
MenuStrip mnMnu = PresenterView.MainMenu;
if (mnMnu.InvokeRequired)
{
// Private variable
_methodInvoker = new MethodInvoker((Action)(() => ConfigureMainMenu(server)));
_methodInvoker.BeginInvoke(new AsyncCallback(ProcessEnded), null); // Call _methodInvoker.EndInvoke in ProcessEnded
}
else
{
/* do work */
}
}
Ответ 2
Вы должны написать что-то вроде этого:
private void ConfigureMainMenu(DIServer server,)
{
MenuStrip mnMnu = PresenterView.MainMenu;
if (mnMnu.InvokeRequired)
{
mnMnu.BeginInvoke(new Action<DIServer>(ConfigureMainMenu),
new object[] { server});
}
else
{
// Do actual work here
}
}
Ответ 3
Вы можете написать метод расширения, который бы обернул анонимные методы и даже позаботился о семантике InvokeRequired
:
public static void InvokeAction(this Control ctl, Action a)
{
if (!ctl.InvokeRequired)
{
a();
}
else
{
ctl.BeginInvoke(new MethodInvoker(a));
}
}
Это позволит вам сделать:
control.InvokeAction(delegate() { ConfigureMainMenu(server); });
Ответ 4
Вы можете сделать это одним методом, вызвав вызов:
ClassData updData = new ClassData();
this.BeginInvoke(new Action<ClassData>(FillCurve),
new object[] { updData });
...
public void FillCurve(ClassData updData)
{
...
}
Ответ 5
Я пробовал кучу разных методов, но никто не работал. то есть...
// Fails -- cannot convert lamda to System.Delegate
mnMnu.BeginInvoke( (DIServer svr)=> {ConfigureMainMenu(server);}, new object[] server);
// Fails -- cannot convert anonymous method to System.Delegate
mnMnu.BeginInvoke( new delegate(DIServer svr){ConfigureMainMenu(server);}, new object[] server);
Итак, короткий ответ - нет. Вы могли бы создать короткие помощники делегатов в данном контексте и использовать lambdas, чтобы сделать его немного опрятным, но это в значительной степени оно.
EDIT: Оказывается, я ошибаюсь. Ниже приведено нижеприведенное описание метода.
Смотрите страница
Ответ 6
Для полностью анонимных методов с ограниченным числом параметров:
Func<int, int?> caller = new Func<int, int?>((int param1) =>
{
return null;
});
caller.BeginInvoke(7, new AsyncCallback((IAsyncResult ar) =>
{
AsyncResult result = (AsyncResult)ar;
Func<int, int?> action = (Func<int, int?>)result.AsyncDelegate;
action.EndInvoke(ar);
}), null);
При необходимости вы можете использовать один из других типов делегатов Func.