Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to know if a Task is being awaited?

I have a method

public Task<Task> DoSomeWorkOnARemoteMachine()

which, very descriptively, executes some work on a remote machine by:

  1. Queueing a message on a message bus signalling that work should be done
  2. A remote agent picks up the message and executes the work
  3. The work finishes and the agent queues a message on a message bus to say that the work is done
  4. The application which invoked the work picks up the message that the work is done

The reason I used Task<Task> is because the first Task<> is for the queueing of the message; while the inner Task is completed when the work has been completed on the remote machine (i.e. when the message from the agent has been received). Any exceptions which the remote agent caught during execution of the work are passed along with the completion message and are re-thrown when the inner Task completes.

To call this method I use:

await await DoSomeWorkOnARemoteMachine();

which would wait for the message to be queued to execute the job, as well as to complete the job and receive any exceptions. However, if I was not interested in whether the job completed on the remote agent or not, I might call it as follows:

await DoSomeWorkOnARemoteMachine();

which would not await the inner Task. However, the inner Task (which receives the message from the remote agent, and re-throws the exceptions) would still execute at some point. I feel that this is a bit of a waste and I would like to avoid executing it when I don't await for the results.

My question is thus: is it possible for a Task to "know" whether it is being awaited and not execute if it is not, or execute some other code path (such as an empty Task body).

I do realize that there are alternatives that I could implement, such as passing a "fire and forget" flag, or adding an overload for "fire and forget". It would be great though if I could implement this without the client API changing

Answers involving other projects which implement this sort of remote work execution would also be great!

like image 606
flipchart Avatar asked Nov 06 '13 07:11

flipchart


People also ask

Does Task run need to be awaited?

If it is some trivial operation that executes quickly, then you can just call it synchronously, without the need for await . But if it is a long-running operation, you may need to find a way to make it asynchronous.

What happens if you do not await a task?

If you don't await the task or explicitly check for exceptions, the exception is lost. If you await the task, its exception is rethrown. As a best practice, you should always await the call. By default, this message is a warning.

Can you await a completed task?

So, yes, you can await already completed tasks. Note that, if you call await several time, it will return it every time and by reference if it's not a value.


1 Answers

I dont think it's easily or efficiently achievable (playing with Task.GetAwaiter is a bad idea, and it will not be accessible from inside your function, see Noseratio's answer). Here is alternative solutions :

Solution n°1 : Function parameter for Task execution

await DoSomeWorkOnARemoteMachine(false) //Indicates that DoSomeWork shouldn't be executed

Solution n°2 : Explicit Task Execution

Task t = await DoSomeWorkOnARemoteMachine() ;
t.Start(); // For example, if you want to execute the resulting Task. 
           // You can also dispatch it to an other thread, etc...
like image 181
Nicolas Voron Avatar answered Sep 22 '22 13:09

Nicolas Voron