طريقة مجهول كمعلمة لBeginInvoke؟
-
06-07-2019 - |
سؤال
لماذا لا يمكنك تمرير طريقة مجهول كمعلمة إلى أسلوب 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()
؟
و(أن تكون قادرة على القيام بذلك من شأنه أن يصلح في تماما مع مفهوم استخدام أساليب حالا / 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
}
}
المحلول
وجرب هذا:
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 */
}
}
نصائح أخرى
ويجب أن تكون قادرا على كتابة شيء من هذا القبيل:
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
}
}
هل يمكن كتابة طريقة التمديد التي من شأنها أن التفاف طرق مجهولة، وحتى تأخذ الرعاية من دلالات 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); });
ويمكنك القيام بذلك في أسلوب واحد من خلال الدعوة استدعاء نفسك:
ClassData updData = new ClassData();
this.BeginInvoke(new Action<ClassData>(FillCurve),
new object[] { updData });
...
public void FillCurve(ClassData updData)
{
...
}
لطرق مجهولة تماما مع عدد محدود من المعلمات:
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);
ويمكنك استخدام أحد أنواع مندوب وظائفها الأخرى حسب الحاجة.
ولقد حاولت مجموعة من أساليب مختلفة ولكن العمل لا شيء. أي ...
// 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 لجعله أكثر إتقانا بعض الشيء ولكن هذا الى حد كبير ذلك.
وتحرير: تبين أن أكون مخطئا. يعمل الجواب methodinvoker أدناه. انظر هذا الصفحة