-2

Command receiver:

public override async ValueTask Execute(){
    // my code here
    // this is boardcast command
    // attempt #1
    Parallel.ForEach(lists, async list => { await DoSomething(); });

    // attempt #2
    List<Task> tasks = new List<Task>();
    foreach(ulong id in ids) tasks.Add(DoSomething());
    await Task.WhenAll(tasks);
}

DoSomething():

public async Task DoSomething(){
    Task<abc> Request = API.RequestSomething();
    // attempt #1
    await Request.ContinueWith(Callback => {
        // Do something (long time...) , eg: update database, update all client data etc.
    });

    // attempt #2
    await Request.ContinueWith(Callback => {
        // .....
    }, TaskContinuationOptions.ExecuteSynchronously);
}

Question is : If client sent command to receiver rapidly (about 100 commands per seconds), how can I handle this without (or low) delay, or how can I make my task function (Task DoSomeThing();) run in parallel

I have tested my code and it works fine. But I would like your advice if there is a better way. Or is there any mistake that I'm missing? (I haven't tested it with multiple commands per second).

  • 2
    "I have tested my code and it works fine." - in that case, everything more is premature optimization. – Thomas Weller Jun 11 '21 at 20:05
  • 2
    Be aware that the `Parallel.ForEach` [is not async friendly](https://stackoverflow.com/questions/67915707/unexpected-different-results-using-task-whenall-and-parallel-foreach-with-an-ent/67923412#67923412). Also combining `ContinueWith` with `await` [is not a good idea](https://stackoverflow.com/questions/18965200/difference-between-await-and-continuewith), since these two mechanisms accomplish the same thing. Use one or the other, and preferably `await`. – Theodor Zoulias Jun 11 '21 at 20:14
  • I tried many methods Until I tried this method, it works, but I don't know if there are any other cases that will cause my code to not work properly. but thanks everyone for the quick replies and suggestions. – MisterA AOM Jun 11 '21 at 20:31

1 Answers1

2

As others have noted, Parallel should not be used with async methods, so the Task.WhenAll approach is the correct solution for asynchronous concurrency:

public override async ValueTask Execute() {
  var tasks = ids.Select(id => DoSomething()).ToList();
  await Task.WhenAll(tasks);
}

Regarding your implementation, do not use ContinueWith:

public async Task DoSomething() {
  var Callback = await API.RequestSomething();
  // Do something (long time...) , eg: update database, update all client data etc.
}
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810