簡體   English   中英

傳遞要異步執行的方法

[英]Passing method to be executed asynch

我正在創建一個Windows窗體應用程序,該應用程序對一條數據執行很多類似的操作。 所有這些操作幾乎相同,因此我想創建一個方法

  • 使用戶界面為只讀
  • 設置諸如“正在執行操作1 ...”之類的消息
  • 異步執行操作,因此用戶界面保持響應
  • 將消息設置為“ Operation1完成”。
  • 將接口只讀設置為false。

我想像這樣調用這種單一方法

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM