0

I have a code to call a function in a loop, which would access endpoints asynchronously, coded like this:

public async Task HitEndPointsAsync()
{
    for (int i = 0; i < _urls.Length; i++)
    {
        await HitOneEndPointAsync(i);
    }
}

The simplified function HitOneEndPointAsync looks like this:

private async Task HitOneEndPointAsync(int i)
{
    var newRec = InsertRec(i);
    ExtURL extUrl = new ExtURL(_urls[i]);
    result = await extUrl.GetAsync(_parms[i]);
    UpdateRec(i, result);
}

If I remove the await in HitEndPointsAsync, then the await that is in HitOneEndPointAsync is no longer effective. If I need all endpoints to be called at once, but on each call await for the response to process that response further, would this be an option? Because as soon as I remove the await at the function call level, the await down the line is ignored. Thoughts?

RamblinRose
  • 4,883
  • 2
  • 21
  • 33
Yogi
  • 410
  • 4
  • 16
  • 4
    Could you clarify what you mean by "no longer effective"? It's not clear to me what you're observing. – Jon Skeet Feb 16 '20 at 18:44
  • Those await would schedule continuations (likely on another thread, that depends on the context). Is that not happening? – Theraot Feb 16 '20 at 18:46
  • "If I remove the await in HitEndPointsAsync, then the await that is in HitOneEndPointAsync is no longer effective" - indeed, so... don't remove that? it is needed! can you clarify *why* you are trying to remove it? – Marc Gravell Feb 16 '20 at 18:49
  • @Marc: Yes, removing it in an attempt to call all endpoints at once without awaitng the completion of each call. However, within each call I need to await for the response – Yogi Feb 16 '20 at 18:54
  • @Jon: by no longer effective I meant that it is not awaiting for the response – Yogi Feb 16 '20 at 18:55
  • @Theraot: The await works, but either both await are on, or no await at all. Can't do await on the lower level, and no await on the upper level – Yogi Feb 16 '20 at 18:56
  • I'm sure it *is* awaiting at the lower level - but if you're not awaiting the result at the higher level, you may be getting confused by what's happening. – Jon Skeet Feb 16 '20 at 19:01
  • @Jon, I can assure you it is not awaiting at the lower level without the await at the upper level. I do have a logging mechanism that logs the response of the httpClient. And the responses are null when the upper await is removed. – Yogi Feb 16 '20 at 19:05
  • 1
    Are you on a console application? By default the continuations would be background threads on the thread pool. They do not prevent the application from ending. – Theraot Feb 16 '20 at 19:19
  • @Yogi: Well, I'd be very surprised if somehow the C# compiler was emitting the wrong code. I think it's *far* more likely that you're misinterpreting the results - I've seen far, far more developers doing that (including myself) than times where the compiler is wrong. If you could provide a [mcve] we could validate that, of course. – Jon Skeet Feb 16 '20 at 20:21

1 Answers1

2

You could try something like this if you don't want to await within the loop:

public async Task HitEndPointsAsync()
{
    var tasks = new List<Task>();

    for (int i = 0; i < _urls.Length; i++)
    {
        tasks.Add(HitOneEndPointsAsync(i));
    }

    await Task.WhenAll(tasks);
}

Note that this may add extra threads due to the calls to HitEndPointAsync being wrapped in a Task so I am not sure it has any advantages over the original version, maybe you could add more context to your question to know exactly what you are trying to do.

Isma
  • 14,604
  • 5
  • 37
  • 51
  • This Task will start multiple threads. I believe it would work but it changes the design. Multiple thread asynchronous instead of single thread asynchronous. Thank you though. Will discuss with the team about this option. – Yogi Feb 16 '20 at 19:00
  • 2
    Replace `new Task` with `Task.Factory.StartNew` instead! – Alb Feb 16 '20 at 19:11
  • 2
    Thanks, I changed it, Task.Run is the preferred way though – Isma Feb 16 '20 at 21:33
  • @Isma, thank you for your suggestion. I had to modify a bit to make it work, like this: tasks.Add(HitOneEndPointsAsync(i)); (Without Task.Run) otherwise it errored out on me. Thanks again – Yogi Feb 17 '20 at 20:19
  • Hi, I updated the answer, I'm glad you solved it ;) – Isma Feb 17 '20 at 20:31