So here\'s the situation: I need to make a call to a web site that starts a search. This search continues for an unknown amount of time, and the only way I know if the searc
It's quite easy to implement with tasks and async/await
, as noted by @KevinS in the comments:
async Task ProcessItemAsync(Item item)
{
while (true)
{
if (await isSearchFinishedAsync(item))
break;
await Task.Delay(30 * 1000);
}
return await downloadDataAsync(item);
}
// ...
var items = getItems();
var tasks = items.Select(i => ProcessItemAsync(i)).ToArray();
await Task.WhenAll(tasks);
var data = tasks.Select(t = > t.Result);
This way, you don't block ThreadPool
threads in vain for what is mostly a bunch of I/O-bound network operations. If you're not familiar with async/await
, the async-await tag wiki might be a good place to start.
I assume you can convert your synchronous methods isSearchFinished
and downloadData
to asynchronous versions using something like HttpClient
for non-blocking HTTP request and returning a Task<>
. If you are unable to do so, you still can simply wrap them with Task.Run
, as await Task.Run(() => isSearchFinished(item))
and await Task.Run(() => downloadData(item))
. Normally this is not recommended, but as you have hundreds of items, it sill would give you a much better level of concurrency than with Parallel.ForEach
in this case, because you won't be blocking pool threads for 30s, thanks to asynchronous Task.Delay
.