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

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

使用 Task.Run 和 Parallel.For 的任務 null

使用 Task.Run 和 Parallel.For 的任務 null

C#
九州編程 2021-12-05 16:49:34
我有兩個最終都會更新同一個對象的服務,因此我們進行了測試以確保對該對象的寫入完成(在幕后我們對每個服務都有重試策略)。10 次中有 9 次,一個或多個理論將失敗,并且task.ShouldNotBeNull();始終是失敗的斷言。這個示例中的異步代碼有什么問題?為什么任務會是空的?    [Theory]    [InlineData(1)]    [InlineData(5)]    [InlineData(10)]    [InlineData(20)]    public async Task ConcurrencyIssueTest(int iterations)    {        var orderResult = await _driver.PlaceOrder();        var tasksA = new List<Task<ApiResponse<string>>>();        var tasksB = new List<Task<ApiResponse<string>>>();        await Task.Run(() => Parallel.For(1, iterations,            x =>            {                tasksA.Add(_Api.TaskA(orderResult.OrderId));                tasksB.Add(_Api.TaskB(orderResult.OrderId));            }));        //Check all tasks return successful                   foreach (var task in tasksA)        {            task.ShouldNotBeNull();            var result = task.GetAwaiter().GetResult();            result.ShouldNotBeNull();            result.StatusCode.ShouldBe(HttpStatusCode.OK);        }         foreach (var task in tasksB)        {            task.ShouldNotBeNull();            var result = task.GetAwaiter().GetResult();            result.ShouldNotBeNull();            result.StatusCode.ShouldBe(HttpStatusCode.OK);        }    }}
查看完整描述

2 回答

?
蕭十郎

TA貢獻1815條經驗 獲得超13個贊

這里不需要 Tasks 和 Parrallel 循環。我假設你的_api調用是 IO 綁定的?你想要更像這樣的東西:


var tasksA = new List<Task<ApiResponse<string>>>();

var tasksB = new List<Task<ApiResponse<string>>>();


//fire off all the async tasks

foreach(var it in iterations){

   tasksA.Add(_Api.TaskA(orderResult.OrderId));

   tasksB.Add(_Api.TaskB(orderResult.OrderId));

}


//await the results

await Task.WhenAll(tasksA).ConfigureAwait(false);


foreach (var task in tasksA)

{

    //no need to get GetAwaiter(), you've awaited above.

    task.Result;


//to get the most out of the async only await them just before you need them

await Task.WhenAll(tasksB).ConfigureAwait(false);


foreach (var task2 in tasksB)

{

     task2.Result;

}

這將觸發您所有的 api 調用,async然后在結果返回時阻塞。您 Parallel for 和 tasks 只是使用額外的線程池線程來實現零收益。


如果_api受 CPU 限制,您可以從中受益,Task.Run但我猜這些是 web api 或其他東西。所以Task.Run除了使用額外的線程之外什么都不做。


查看完整回答
反對 回復 2021-12-05
?
嗶嗶one

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

正如其他人所建議的那樣,刪除Parallel, 和await在asserting他們之前完成的所有任務。


我還建議.Result從每個任務中刪除,而await不是它們。


public async Task ConcurrencyIssueTest(int iterations)

{

    var orderResult = await _driver.PlaceOrder();


    var taskA = _Api.TaskA(orderResult.OrderId);

    var taskB = _Api.TaskB(orderResult.OrderId);


    await Task.WhenAll(taskA, taskB);


    var taskAResult = await taskA;


    taskAResult.ShouldNotBeNull();

    taskAResult.StatusCode.ShouldBe(HttpStatusCode.OK);


    var taskBResult = await taskB;


    taskBResult.ShouldNotBeNull();

    taskBResult.StatusCode.ShouldBe(HttpStatusCode.OK);

}


查看完整回答
反對 回復 2021-12-05
  • 2 回答
  • 0 關注
  • 164 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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