亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何將異步方法放在列表中并迭代調用它們?

如何將異步方法放在列表中并迭代調用它們?

C#
慕無忌1623718 2022-07-23 17:11:23
最近我想對服務調用列表進行健康檢查。它們都是異步任務(例如Task<IHttpOperationResponse<XXX_Model>> method_name(...)我想將它們全部放入一個列表中。我遵循了這篇文章的答案:Storing a list of methods in C#然而,它們是異步方法。我這樣說:async 方法的集合List<Action> _functions = new List<Action> {       () => accountDetailsServiceProvider.GetEmployer(EmployerId),                                         () => accountServiceProvider.GetAccountStatus(EmployerId)}有人可以指導我以正確的方式實現將異步方法放入列表并迭代調用它們嗎?提前致謝!
查看完整描述

3 回答

?
鳳凰求蠱

TA貢獻1825條經驗 獲得超4個贊

首先,您需要使您的方法異步。這意味著他們必須返回一個任務。例如:


public static async Task Foo()

{

    await Task.Delay(1);

    Console.WriteLine("Foo!");

}


public static async Task Bar()

{

    await Task.Delay(1);

    Console.WriteLine("Bar!");

}

然后要將它們放入列表中,您必須將列表定義為包含正確的類型。由于異步方法實際上返回了一些東西,所以它是一個 Func,而不是一個動作。它返回一個任務。


var actions = new List<Func<Task>>

{

    Foo, Bar

};

要調用它們,請在列表中選擇(使用 Linq)來調用它們。這將創建一個任務列表來代替功能列表。


var tasks = actions.Select( x => x() );

然后等待他們:


await Task.WhenAll(tasks);

完整示例:


public static async Task MainAsync()

{

    var actions = new List<Func<Task>>

    {

        Foo, Bar

    };

    var tasks = actions.Select( x => x() );

    await Task.WhenAll(tasks);

}

輸出:


Foo!

Bar!

DotNetFiddle 上的示例


如果你的方法返回一個布爾值,那么返回類型就變成Task<bool>了,其余的也一樣:


public static async Task<bool> Foo()

{

    await Task.Delay(1);

    Console.WriteLine("Foo!");

    return true;

}


public static async Task<bool> Bar()

{

    await Task.Delay(1);

    Console.WriteLine("Bar!");

    return true;

}


var actions = new List<Func<Task<bool>>>

{

    Foo, Bar

};


var tasks = actions.Select( x => x() );


await Task.WhenAll(tasks);

在等待它們之后,您可以使用另外一條 LINQ 語句將任務轉換為它們的結果:


List<bool> results = tasks.Select( task => task.Result ).ToList();


查看完整回答
反對 回復 2022-07-23
?
ITMISS

TA貢獻1871條經驗 獲得超8個贊

根據評論:


但是,我的任務需要每個方法調用的布爾值,因為無論服務是否關閉,我都必須向前端報告狀態


為將返回所需布爾值的方法創建一個包裝器方法


public async Task<Result> Check(string name, Func<Task> execute)

{

    try

    {

        await execute();

        return new Result(name, true, string.Empty);

    }

    catch (Exception ex)

    {

        return new Result(name, false, ex.Message);

    }

}


public class Result

{

    public string Name { get; }

    public bool Success { get; }

    public string Message { get; }

    public Result(string name, bool success, string message) 

        => (Name, Success, Message) = (name, success, message);

}

然后您不需要收集代表,而是收集Task.


var tasks = new[]

{

    Check(nameof(details.GetEmployer), () => details.GetEmployer(Id)),

    Check(nameof(accounts.GetAccountStatus), () => accounts.GetAccountStatus(Id)),

};


var completed = await Task.WhenAll(tasks);


foreach (var task in completed)

{

    Console.WriteLine($"Task: {task.Name}, Success: {task.Success};");

}


查看完整回答
反對 回復 2022-07-23
?
慕神8447489

TA貢獻1780條經驗 獲得超1個贊

我想你只是在尋找像這樣簡單的東西?


var myList = new List<Action>()

{

    async() => { await Foo.GetBarAsync(); },

    ...

};

我建議您將類型從更改Action為Func<Task>喜歡。


var myList = new List<Func<Task>>()

{

  async() => { await Foo.GetBarAsync(); },

};

您可以在此處閱讀有關原因的更多信息:https ://blogs.msdn.microsoft.com/pfxteam/2012/02/08/potential-pitfalls-to-avoid-when-passing-around-async-lambdas/


調用(簡化)


foreach (var action in myList)

{

    await action.Invoke();

}


查看完整回答
反對 回復 2022-07-23
  • 3 回答
  • 0 關注
  • 118 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號