C# 传递要异步执行的方法
我正在创建一个Windows窗体应用程序,它对一段数据执行许多类似的操作。所有这些操作几乎相同,因此我想创建一个C# 传递要异步执行的方法,c#,.net,winforms,asynchronous,async-await,C#,.net,Winforms,Asynchronous,Async Await,我正在创建一个Windows窗体应用程序,它对一段数据执行许多类似的操作。所有这些操作几乎相同,因此我想创建一个 使用户界面为只读 设置消息,如“正在执行操作1…” 异步执行操作,因此用户界面保持响应 将消息设置为“操作1已完成” 将接口只读设置为false 我想把这个方法称为 ExecuteOperation([method to execute], "Executing operation1") 我确信这很简单,但我在委托和任务之间迷失了方向,因此请告诉我如何编写能够运行选定方法的方法
- 使用户界面为只读
- 设置消息,如“正在执行操作1…”
- 异步执行操作,因此用户界面保持响应
- 将消息设置为“操作1已完成”
- 将接口只读设置为false
ExecuteOperation([method to execute], "Executing operation1")
我确信这很简单,但我在委托和任务之间迷失了方向,因此请告诉我如何编写能够运行选定方法的方法,最好是使用多个参数,以及如何调用此方法
注意:
我指的是禁用接口
MainMenu.Enabled = false;
txtData.ReadOnly = true;
您可能正在寻找类似的内容(我在这里展示了一个获取参数的方法的示例,因为您特别要求使用该示例): 如果您有各种操作可以抛出的标准异常,并且会导致某种类型的UI反馈,那么您很可能还希望在ExecuteOperation包装中添加一些异常处理
另一方面,我对名称和操作进行了重新排序,因为这使传递匿名方法作为操作变得更为简洁(IMO)。您可能正在寻找类似的内容(我在这里展示了一个获取参数的方法的示例,因为您特别要求该示例): 如果您有各种操作可以抛出的标准异常,并且会导致某种类型的UI反馈,那么您很可能还希望在ExecuteOperation包装中添加一些异常处理
另一方面,我对名称和操作进行了重新排序,因为这使传递匿名方法作为操作更为简洁(IMO)。类似的内容(非异步/等待-版本)如何:
void Foo(操作、字符串消息)
{
使界面只读和设置消息(消息)的方法;
BackgroundWorker工人=新的BackgroundWorker();
worker.DoWork+=(obj,arg)=>action.Invoke();
worker.RunWorkerCompleted+=
(obj,arg)=>
{
方法,该方法使接口ReadWrite();
};
worker.RunWorkerAsync();
}
在我意识到您需要异步/等待和特定任务之前,我写了这篇文章——然而,其他人已经回答了这个问题。您可以为您的操作的额外参数创建任何您想要的重载。类似这样的内容如何(非异步/等待-版本):
void Foo(操作、字符串消息)
{
使界面只读和设置消息(消息)的方法;
BackgroundWorker工人=新的BackgroundWorker();
worker.DoWork+=(obj,arg)=>action.Invoke();
worker.RunWorkerCompleted+=
(obj,arg)=>
{
方法,该方法使接口ReadWrite();
};
worker.RunWorkerAsync();
}
在我意识到您需要异步/等待和特定任务之前,我写了这篇文章——然而,其他人已经回答了这个问题。可以为操作的额外参数创建任何重载。可以说,可以将方法传递到方法中,但委托必须匹配。如果您有具有不同签名的方法,那么您的角度是错误的 动作和函数委托是通用的。有一个可以匹配几乎任何签名(最多16个参数),但同样,它们必须匹配方法签名。如果一个方法具有一个参数,另一个方法具有两个参数,或者两个方法具有不同类型的参数,则不能将这些参数传递给同一个委托 所以,这实际上取决于你的方法有多相似。如果它们有不同类型的参数,您可能必须“包装”这些调用 简化示例:
void Main()
{
List<Action> actions = new List<Action>
{
() => Method1("myString"),
() => Method2("myString2", "myString3")
};
foreach(var action in actions) InvokeAction(action);
}
void InvokeAction(Action action)
{
action();
}
void Method1(string x)
{
Console.WriteLine(x);
}
void Method2(string y, string z)
{
Console.WriteLine(y);
Console.WriteLine(z);
}
void Main()
{
列表操作=新列表
{
()=>Method1(“myString”),
()=>Method2(“myString2”、“myString3”)
};
foreach(动作中的var动作)InvokeAction(动作);
}
无效调用(操作)
{
动作();
}
无效方法1(字符串x)
{
控制台写入线(x);
}
无效方法2(字符串y、字符串z)
{
控制台写入线(y);
控制台写入线(z);
}
另一方面,如果您的方法具有相同的签名,则更简单一些:
void Main()
{
InvokeAction(Method1, "myString");
InvokeAction(Method2, "myString2");
}
void InvokeAction(Action<string> action, string param)
{
action(param);
}
void Method1(string x)
{
Console.WriteLine(x);
}
void Method2(string y)
{
Console.WriteLine(y);
}
void Main()
{
InvokeAction(Method1,“myString”);
调用(方法2,“myString2”);
}
void InvokeAction(操作,字符串参数)
{
行动(参数);
}
无效方法1(字符串x)
{
控制台写入线(x);
}
无效方法2(字符串y)
{
控制台写入线(y);
}
现在,对于异步运行,如果您使用的是.NET4.0,那么它就像使用System.Threading.Task一样简单。您可以将我的示例方法更改为:
void InvokeAction(Action<string> action, string param)
{
Task.Factory.StartNew(() => action(param));
}
void InvokeAction(动作动作,字符串参数)
{
Task.Factory.StartNew(()=>action(param));
}
可以说,您可以将方法传递到方法中,但代理必须匹配。如果您有具有不同签名的方法,那么您的角度是错误的
动作和函数委托是通用的。有一个可以匹配几乎任何签名(最多16个参数),但同样,它们必须匹配方法签名。如果一个方法具有一个参数,另一个方法具有两个参数,或者两个方法具有不同类型的参数,则不能将这些参数传递给同一个委托
所以,这实际上取决于你的方法有多相似。如果它们有不同类型的参数,您可能必须“包装”这些调用
简化示例:
void Main()
{
List<Action> actions = new List<Action>
{
() => Method1("myString"),
() => Method2("myString2", "myString3")
};
foreach(var action in actions) InvokeAction(action);
}
void InvokeAction(Action action)
{
action();
}
void Method1(string x)
{
Console.WriteLine(x);
}
void Method2(string y, string z)
{
Console.WriteLine(y);
Console.WriteLine(z);
}
void Main()
{
列表操作=新列表
{
()=>Method1(“myString”),
()=>Method2(“myString2”、“myString3”)
};
foreach(动作中的var动作)InvokeAction(动作);
}
无效调用(操作)
{
动作();
}
无效方法1(字符串x)
{
控制台写入线(x);
}
无效方法2(字符串y、字符串z)
{
控制台写入线(y);
控制台。WriteLin
void InvokeAction(Action<string> action, string param)
{
Task.Factory.StartNew(() => action(param));
}