[英]Passing method to be executed asynch
我正在創建一個Windows窗體應用程序,該應用程序對一條數據執行很多類似的操作。 所有這些操作幾乎相同,因此我想創建一個方法
我想像這樣調用這種單一方法
ExecuteOperation([method to execute], "Executing operation1")
我敢肯定這很簡單,但是我在委托和任務之間迷路了,因此請向我展示如何編寫一種能夠運行選定方法(最好具有多個參數)的方法以及如何調用該方法。
注意:
通過禁用接口,我的意思是
MainMenu.Enabled = false;
txtData.ReadOnly = true;
您可能正在尋找類似的東西(我在此處顯示了一個帶有參數的方法的示例,因為您專門詢問了這種情況):
private async Task ExecuteOperation(string operationName, Action action)
{
//Disable UI here
//Set 'Executing' message here
await Task.Run(action);
//Set 'Finished' message here
//Enable UI here
}
private async Task CallOperation()
{
int x, y, z; //These get set to something here...
await ExecuteOperation("Operation1", () => OperationWithParams(x, y, z));
}
如果您有各種操作可能引發的標准異常,並且應該導致某種形式的UI反饋,則您很可能還希望在ExecuteOperation包裝器中添加一些異常處理。
附帶說明一下,我對名稱和操作進行了重新排序,因為這使傳遞匿名方法作為操作在某種程度上更干凈(IMO)。
可以說,可以將方法傳遞給方法,但是委托必須匹配。 如果您使用的方法具有不同的簽名,那么您將陷入錯誤的困境。
Action和Func委托是通用的。 有一個可以匹配幾乎所有簽名(最多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()
{
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);
}
現在,關於異步運行,如果您使用的是.NET 4.0,則就像使用System.Threading.Task一樣簡單。 您可以這樣更改我的示例方法:
void InvokeAction(Action<string> action, string param)
{
Task.Factory.StartNew(() => action(param));
}
這樣的事情(非異步/等待-版本)怎么樣:
void Foo<T>(Action<T> action, string message)
{
MethodWhichMakesMyInterfaceReadOnlyAndSetsMessage(message);
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (obj, arg) => action.Invoke();
worker.RunWorkerCompleted +=
(obj, arg) =>
{
MethodWhichMakesMyInterfaceReadWrite();
};
worker.RunWorkerAsync();
}
我在意識到您想要異步/等待和特定任務之前就寫了這篇文章-但是其他人對此做出了回應。 您可以為操作的額外參數創建所需的任何重載。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.