1

Let's say i have 2 task (A and B). I can run them in parallel completely, so i can use:

await Task.WhenAll(A,B)
var resA = await A;
var resB = await B;

Now i would like to not wait for B if A (based on some condition) returns false. The result of B does not interest me anymore. Can this be done?


In addition to this answers below:

So just to be sure, a Task starts immediately when creating one. So the following code should work.

var A = Usermanager.FindAsync(email.ToString(), password.ToString());
var B = db.Table.AnyAsync(r=> r.email == email.Tostring()); //simplified action
var user = await A;
if (user != null)
{
    var resB = await B;
}
else
{
    // A was false, so don't await B
}

And if B generates a long running sql-statement. Would it be better to still use the cancellation token resulting in following code to free up the SQL Servers resources?

var cts = new CancellationTokenSource();
var A = Usermanager.FindAsync(email.ToString(), password.ToString());
var B = db.Table.AnyAsync(r=> r.email == email.Tostring(), cts.Token); //simplified long running sql action
var user = await A;
if (user != null)
{
    var resB = await B;
}
else
{
    // A was false, cancel query from B
    cts.Cancel();
}
P. Zantinge
  • 185
  • 1
  • 15

2 Answers2

3

Now i would like to not wait for B if A (based on some condition) returns false. The result of B does not interest me anymore. Can this be done?

Sure, just don't await it:

if (await A)
{
  var resB = await B;
}
else
{
  // A was false, so don't await B
}
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • this way both actions are executed synchronous (in perspective to each other) I would like to start A and B at the same time (async) but Ignore B – P. Zantinge Jul 31 '17 at 15:42
  • @Dexter Then start `B` before awaiting `A`, just don't `await` B. – Servy Jul 31 '17 at 15:58
  • @Dexter: In this code, `A` and `B` are both tasks, and they are both already in progress. They are not executed synchronously nor serially. – Stephen Cleary Jul 31 '17 at 16:00
  • Could you explain a bit more? I edited the question with a followup base on your answer. It wouldn't fit in a comment. – P. Zantinge Aug 02 '17 at 08:34
  • @Dexter: Yes, [TAP tasks are returned "hot"](https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap#task-status) - that is, already in progress. And yes, if `B` is long running and consuming resources and cancelable, then it would be a good idea to cancel it as per your code. – Stephen Cleary Aug 02 '17 at 12:47
  • then the real question for task B is: Are EF6 queries cancalable once send to the SQL-Server. I couldn't find a satisfying answer telling why ore why not. – P. Zantinge Aug 03 '17 at 10:23
  • @Dexter: Ah, yes. I don't know whether those are truly cancelable. But if they're not, there isn't anything you can do about it anyway (short of killing the db connection). – Stephen Cleary Aug 03 '17 at 12:46
-2

a removed answer was linking to How to cancel and raise an exception on Task.WhenAll if any exception is raised?. But guessing on the mins following code is not the correct way to go:

var cts = new CancellationTokenSource();
var A = Usermanager.FindAsync(email.ToString(), password.ToString());
var B = db.Table.AnyAsync(r=> r.email == email.Tostring(), cts.Token) //simplified action
var C = A.ContinueWith(t => { if (t.Result == null) { cts.Cancel(); } }, TaskContinuationOptions.OnlyOnRanToCompletion);
await Task.WhenAll(C,B);

Of course you can change the ContinuationOption, but to use the result of a task, i believe it should be OnlyRanToCompletion. Above should cancel B and therefor finish the Task.WhenAll command when A has a result of null (no result).

P. Zantinge
  • 185
  • 1
  • 15