How to make asynchronous calls from List.ForEach C #

I have a list of elements for each element that I want to call the UploadChunkToServer method, but in parallel. There will always be only 4 items in the list.

if (DataQueue.Count == NumberofChunksToRead)
{
    DataQueue.ToList().ForEach(Chunk =>
    {
        UploadChunkToServer(Chunk);
    });
}

Above is my code call in the method and the method signature is as follows.

private void UploadChunkToServer(UserCustomFile Chunk)
{
    var client = new RestClient(Helper.GetServerURL());

    var request = new RestRequest("api/fileupload/savechunk", Method.POST);
    request.AddHeader("Content-type", "application/json");
    request.RequestFormat = RestSharp.DataFormat.Json;
    request.AddJsonBody(Chunk);

    client.ExecuteAsync(request, response =>
    {
        if (response.StatusCode != System.Net.HttpStatusCode.OK)
        {
            throw new Exception(response.ErrorMessage);
        }
        else
        {
            ChunkStatuses.Add(Chunk.ChunkID);
        }
    });
}

I tried to add an asynchronous statement, but no luck. Any ideas on how to do this?

+4
source share
4 answers

Perhaps you can use Parallel and ForEach in particular:

Parallel.ForEach(DataQueue.ToList(), Chunk =>
                 {
                      UploadChunkToServer(Chunk);
                 });
+2
source

Your question is a bit unclear, and I think you have mixed up asynchronous and parallel, which do not necessarily coincide with C #.

There are two types of asynchronization in C # :

  • / (/ ..)

  • ( ..)

-, , , ( ). , .

, , - , Async [YourMethodName], API , TaskCompletionSource . , ( Task.Run - ), ( , , [YourMethodName] Async) , .

, , client.ExecuteAsync , , ExecuteAsync a Task. :

// add async keyword to notify that you are awaitng int he method
// perhaps also change the void to Task
private async Task UploadChunkToServer(UserCustomFile Chunk)
{
    var client = new RestClient(Helper.GetServerURL());

    var request = new RestRequest("api/fileupload/savechunk", Method.POST);
    request.AddHeader("Content-type", "application/json");
    request.RequestFormat = RestSharp.DataFormat.Json;
    request.AddJsonBody(Chunk);

    //add await operator to make this part run acync
    return await client.ExecuteAsync(request, response =>
    {
        if (response.StatusCode != System.Net.HttpStatusCode.OK)
        {
            throw new Exception(response.ErrorMessage);
        }
        else
        {
            ChunkStatuses.Add(Chunk.ChunkID);
        }
    });
}

:

  if (DataQueue.Count == NumberofChunksToRead)
  {
       DataQueue.ToList().ForEach(Chunk =>
       {
           await UploadChunkToServer(Chunk);
       });
  }

Task, , ..

, Parallel Foreach . , , , -. , , - , , . 4- , 4 , , , . -, .

+1

:

var tasks = new List<Task<bool>>();

DataQueue.ToList().ForEach(chunk =>
{
      tasks.Add(Task.Run(() => UploadChunkToServer(chunk)));
});

await tasks.WhenAll();

UploadChunkToServer, - ; a bool , . void Tasks , ...

UPDATE: TheBoyan , async UploadChunkToServer, -, . , :

var tasks = new List<Task<bool>>();

DataQueue.ToList().ForEach(chunk =>
{
    tasks.Add(UploadChunkToServer(chunk));
});

await tasks.WhenAll();

UploadChunkToServer :

private async Task<bool> UploadChunkToServer(UserCustomFile Chunk)
{
    var client = new RestClient(Helper.GetServerURL());

    var request = new RestRequest("api/fileupload/savechunk", Method.POST);
    request.AddHeader("Content-type", "application/json");
    request.RequestFormat = RestSharp.DataFormat.Json;
    request.AddJsonBody(Chunk);

    return await client.ExecuteAsync(request, response =>
    {
        if (response.StatusCode != System.Net.HttpStatusCode.OK)
        {
            throw new Exception(response.ErrorMessage);
        }
        else
        {
            ChunkStatuses.Add(Chunk.ChunkID);
            return true;
        }
    });
}
0

You cannot do this because the ForEach parameter is a great function called ForEach, not the part of your fuction that is asynchronous - BUT - the actual solution is to not use ForEach - foreach is actually a little shorter and does not work This problem has

if (DataQueue.Count == NumberofChunksToRead)
{
    forach(var Chunk in DataQueue.ToList())
    {
        await UploadChunkToServer(Chunk);
    }
}
-1
source

Source: https://habr.com/ru/post/1691614/


All Articles