Task.WaitAll-结果被覆盖

问题描述

在循环中,我正在使用Task.Run(// ...)创建一个任务。每个任务都包含一个WebRequest。在Task.WaitAll处,一个任务的结果被另一个任务的结果覆盖。我在做什么错? 当尝试使用调试器时,它可以正常工作。是因为并发吗?如何解决呢? 以下是我的代码段:

SomeMethod()
{
   //someItemList.Count() == 5
   int r = 0;
   Task<MyModel>[] myTaskList= new Task<MyModel>[5];
   foreach(var item in someItemList){
       Task<MyModel> t = Task<MyModel>.Run(() => { return 
           SomeOperationWithWebRequest(item); });
       myTaskList[r] = t;
       r++;
   }
   Task.WaitAll(myTaskList); //myTaskList[0].Result...myTaskList[4].Result all are having same output.

  
}

MyModel SomeOperationwithWebRequest(Item){
    
            string URL = "SomeURLFromItem";
            string DATA = "DATAfromItem"
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
            request.Method = "POST";
            request.ContentType = "application/json";
            request.ContentLength = DATA.Length;
            using (Stream webStream = request.GetRequestStream())
            using (StreamWriter requestWriter = new StreamWriter(webStream,System.Text.Encoding.ASCII))
            {
                requestWriter.Write(DATA);
            }
            try
            {
                WebResponse webResponse = request.GetResponseAsync();
                using (Stream webStream = webResponse.GetResponseStream() ?? Stream.Null)
                using (StreamReader responseReader = new StreamReader(webStream))
                {
                  //response
                }

            catch (Exception ex)
            {

            }
            return new MyModel() { // properties
                };
}

解决方法

我认为它可以在调试中使用,因为您不必等待异步WebRequest。试试这个:

private readonly List<string> _someItemList = new List<string> { "t1","t2","t3" };

private async Task SomeMethodAsync()
{
    var myTaskList = new List<Task<MyModel>>();
    int counter = 0;
    foreach (var item in _someItemList)
    {
        var t = Task.Run(() => SomeOperationWithWebRequestAsync(counter++));
        myTaskList.Add(t);
    }
    await Task.WhenAll(myTaskList);
}

public async Task<MyModel> SomeOperationWithWebRequestAsync(int counter)
{
   //do your async request,for simplicity I just do a delay
    await Task.Delay(counter * 1000);
    return new MyModel {Counter = counter };
}

public class MyModel
{
    public int Counter { get; set; }
}

并像这样使用它:

 await SomeMethodAsync();

还要注意Task.WhenAll与Task.WaitAll参见例如 WaitAll vs WhenAll