I’m trying to write some code that will make a web service call to a number of different servers in parallel, so TPL seems like the obvious choice to use.
Only one of my web service calls will ever return the result I want and all the others won’t. I’m trying to work out a way of effectively having a Task.WaitAny but only unblocking when the first Task that matches a condition returns.
I tried with WaitAny but couldn’t work out where to put the filter. I got this far:
public void SearchServers()
{
var servers = new[] {"server1", "server2", "server3", "server4"};
var tasks = servers
.Select(s => Task<bool>.Factory.StartNew(server => CallServer((string)server), s))
.ToArray();
Task.WaitAny(tasks); //how do I say "WaitAny where the result is true"?
//Omitted: cancel any outstanding tasks since the correct server has been found
}
private bool CallServer(string server)
{
//... make the call to the server and return the result ...
}
Edit: Quick clarification just in case there’s any confusion above. I’m trying to do the following:
- For each server, start a
Taskto check it - Either, wait until a server returns true (only a max of 1 server will ever return true)
- Or, wait until all servers have returned false, i.e. there was no match.
The best of what I can think of is specifying a
ContinueWithfor eachTask, checking the result, and iftruecancelling the other tasks. For cancelling tasks you may want to use CancellationToken.UPDATE: An alternative solution would be to
WaitAnyuntil the right task completed (but it has some drawbacks, e.g. removing the finished tasks from the list and creating a new array out of the remaining ones is quite a heavy operation):UPDATE 2: Nowadays I would do it with Rx:
The test takes 3.32 seconds on my machine (that means it didn’t wait for the 4th server) and I got the following output: