7

I have the following code:

//Await #1

var response1 = await doSomething();

if(response1.isSuccess) {

//Await #2

var response2 = await doSomethingElse();

}

Response 1 and response 2 are totally independent and i want to parallelize the await task here. Basically response 2 takes a lot of time and hence is only invoked when response1 is success. Is there any way in which i can invoke both tasks and see the result of response 1 and if it is fail, i drop/skip the response of Await#2.

Prasad Telkikar
  • 15,207
  • 5
  • 21
  • 44
Shubham
  • 83
  • 4
  • your current code is ok, it will only call doSomethingElse if doSomething succeess – Ehsan Sajjad Dec 24 '19 at 09:47
  • You mean you want to start them together, but if response 1 finishes first, and it did not succeed, you want to cancel response 2? – Sweeper Dec 24 '19 at 09:47
  • you can use task factory start new task and at end wait for both the tasks. – Kaushik Dec 24 '19 at 09:51
  • @Sweeper, yes that is what i am trying. Is that achievable? – Shubham Dec 24 '19 at 09:53
  • I think you use [ContinueWith](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.continuewith?view=netframework-4.8) `Task t = Task.Run(() => doA()); t.ContinueWith((t1) => { doB(); });` – styx Dec 24 '19 at 10:02

4 Answers4

11

Essentially what you want is to cancel a task, but with a little more logic.

You need to edit doSomethingElse so that it accepts a CancellationToken, and also so that it makes use of it to stop what its doing:

public async Task<Foo> DoSomethingElse(CancellationToken token) {
    ...
    if (token.IsCancellationRequested) {
        // stop what you are doing...
        // I can't tell you how to implement this without seeing how DoSomethingElse is implemented
    }
    ...
}

Now, get a CancellationToken from a CancellationTokenSource:

var source = new CancellationTokenSource();
var token = source.Token;

And here comes the logic of "if response 1 fails cancel response 2":

var response2Task = DoSomethingElse(token);
var response1 = await DoSomething();
if (!response1.IsSuccess) {
    source.Cancel();
} else {
    var response2 = await response2Task;
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
4
var task2 = doSomethingElse();
var response1 = await doSomething();

if(response1.isSuccess) {
    var response2 = await task2;
}

This will start the execution of doSomethingElse() immediately, and only wait for its completion when response1.isSuccess == true

Piotr L
  • 939
  • 1
  • 6
  • 12
0

You can launch both threads, then once the first task obtains a result, you could either stop, or 'wait' for the second thread to finish.

The conditional logic, imo, should be placed in the first task's thread. If you do not have access to the doSomething, make a lambda in which you will await doSomething's response and then proceed with the condition logic.

How to stop a thread? Here you go, and here you go

Artur
  • 334
  • 5
  • 15
-1

This is what you can do:

            var task1 = Task.Run(() =>
            {
                Console.WriteLine("running task 1");
                return 1;
            });

            var task2 = Task.Run(() =>
            {
                Console.WriteLine("running task 2");
                return 2;
            });

            await Task.WhenAll(task1, task2);

So you will run the 2 tasks in parallel. If you need to check the result of particular tasks, this is the way to do that(it won't trigger the task again if you run Task.WhenAll() previously. It will just get you the results of previously executed tasks):

var result1 = await task1;
var result2 = await task2;

Then you can apply some condition:

if(result1 == 1) return result2;

etc..

OlegI
  • 5,472
  • 4
  • 23
  • 31