简体   繁体   中英

Call async in sync foreach

I've got external library with eventCallback defined like this :

public delegate void processEvent(string deviceType, string deviceId,string evtName, string format, string data);
        // event for event callback
        public event processEvent eventCallback;

in my code I subscribe to this event this way

app.eventCallback += ProcessEvent;
    protected void ProcessEvent(string deviceType, string deviceId, string eventName, string format, string data)
{
            var requests = GetRequests();
            foreach (var serviceRequest in requests)
        {   
            client.callAsync(serviceRequest)
        }
}

the question is how to call client.callAsync asynchronous ? I can't change signature of ProcessEvent to return Task since then I cant bind it to eventCallback += ProcessEvent;

callAsync is async method

Should I create list of tasks and then wait for all or is there some better way ?

Just add async to the method signature:

 protected async void ProcessEvent(string deviceType, string deviceId, string eventName, string format, string data)

This works because you aren't changing the return type. Then change the call to:

await client.callAsync(serviceRequest);

Might also want to use ConfigureAwait(false) here.

If you want to run all service requests at once, asynchronously, change your foreach to:

await Task.WhenAll(requests.Select(x => client.callAsync(x));

Or you can use a collection of Tasks if you want. Same effect.

Written as you have it your event handler does one request at a time.

If you want to block on every Task completing you can do this (which does not require async or await):

Task.WhenAll(requests.Select(x => client.callAsync(x)).Wait();

While they sound similar, await and Task.Wait are conceptually very different things. In short, the former is non-blocking, the latter is blocking.

If you need to wait until all tasks finish before returning then I think there is no better way than creating a list of tasks and waiting for all. Eg

Task.WaitAll(requests.Select(x => Task.Run(async (x) => await client.callAsync(x)));

Above code will run each task on a separate thread and then block the main thread until all of them ends.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM