1

I have the following function that call my API:

private async void applyMe(int id, string data)
{
   string url = $"https://localhost:44382/api/isc/getdata?id=" + id + "&data=" + data;
   ApiHelper.InitializeClient();
   string _apiResult = await APIProcessor.LoadApi(url);     
}

API Helper

public static class ApiHelper
{
    public static HttpClient ApiClient { get; set; }
    public static void InitializeClient() 
    {
        ApiClient = new HttpClient();
        ApiClient.DefaultRequestHeaders.Accept.Clear();
        ApiClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/jason"));
    }
}

APIProcessor

public class APIProcessor
{
    public static async Task<string> LoadApi(string url)
    {
        using (HttpResponseMessage response = await ApiHelper.ApiClient.GetAsync(url))
        {
            if (response.IsSuccessStatusCode)
            {
                string _apiResult = await response.Content.ReadAsStringAsync();
                return _apiResult;
            }
            else
            {
                throw new Exception(response.ReasonPhrase);
            }
        }
    }
}

I want to call my API inside foreach loop as below

using (myEntities _context = new myEntities ())
{
    foreach (var item in _context.items.Where(s => s.id >= 1 && s.id <= 500))
      {
          applyMe(item.id, item.data);
      }
 }

The API not calling yet because of async await :( Please how can I solve this issue?

6
  • await getData(...? Commented Feb 28, 2021 at 16:15
  • @Charlieface Forget the name of API, I changed it Commented Feb 28, 2021 at 16:21
  • 1
    OK await applyMe(... the name of the function wasn't my point obviously. You need to await an async function Commented Feb 28, 2021 at 16:22
  • @Charlieface How? Commented Feb 28, 2021 at 16:24
  • 3
    It's async Task all the way up, until you get to the UI event handler, then use async void. So declare private async Task applyMe(... Commented Feb 28, 2021 at 16:25

3 Answers 3

2

Use Task.WhenAll(). It returns an awaitable that will get completed when all other tasks are finished. In the end you need to wait without blocking the thread. see microsoft doc

using (myEntities _context = new myEntities ())
{
    await Task.WhenAll(_context.items
                               .Where(s => s.id >= 1 && s.id <= 500)
                               .Select(s => applyMe(item.id, item.data))
                      );
}

Important! The applyMe should return a Task and not remain void. The async void pattern is not recommended.

Sign up to request clarification or add additional context in comments.

Comments

0

Two small adjustments to make this work: First Task iso void

private async Task getData(int id, string data)
{
    string url = $"https://localhost:44382/api/isc/getdata?id=" + id + "&data=" + data;
    ApiHelper.InitializeClient();
    string _apiResult = await APIProcessor.LoadApi(url);     
}

and second, await the getData call

using (myEntities _context = new myEntities ())
{
    foreach (var item in _context.items.Where(s => s.id >= 1 && s.id <= 500))
      {
          await getData(item.id, item.data);
      }
 }

Comments

0

You could use IAsyncEnumerable<MyModel> (docs)

public IAsyncEnumerable<MyModel> GetItems()
{
    IQueryable<T> query = this._context.items;

    query = query.Where(s => s.id >= 1 && s.id <= 500);

    return query.AsAsyncEnumerable();
}

And use it with:

IAsyncEnumerable<MyModel>> items = GetItems();
await foreach (var myModel in items)
{
    //Call external api         
}                

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.