Home > Software engineering >  How a task is constructed when using Invoke on a delegate?
How a task is constructed when using Invoke on a delegate?

Time:01-23

delegate Task MyDelegate();
event MyDelegate d;

d  = () => Task.Delay(100);
d  = () => Task.Delay(200);
d  = () => Task.Delay(300);

var t = d.Invoke();

await Task.Delay(1000);

After invoking by Invoke status is:

Id = 1, Status = WaitingForActivation, Method = {null}.

After delay, so when all tasks are finished it's:

Id = 1, Status = RanToCompletion, Method = {null}.

Does it mean that Invoke executes Task.WhenAll implicitly or it's internal mechanism is even something different?

CodePudding user response:

Delegate combining has no knowledge of Task or await. As you note, it will execute all of them and return the last one. The delegate will simply drop the others on the floor and only return the last.

But in this case, Task.Delay does not execute anything, it just returns a "promise" which you have to await. If you do not await it then no delay happens.

And that final result you are also dropping on the floor, as you do not await t. The only Delay actually working is the final await Task.Delay(1000);

delegate Task MyDelegate();
event MyDelegate d;

d  = () => Task.Delay(100);  // Just returns a Task when executed, does NOT block
d  = () => Task.Delay(200);
d  = () => Task.Delay(300);
// Nothing has happened yet!!

var t = d.Invoke();
// All delegates are executed synchronously, but only the final result is returned.
// Each delegate returned a Task but did not block for the delay amount.
// Result is also dropped so no delay happens at all.

await Task.Delay(1000);
// Final real delay of 1000

If you had changed the last line to await t; instead, you would have waited for 300ms, not the total 600ms.

You can see all this in action in this dotnetfiddle.

CodePudding user response:

After quick experiment with integers seems it returns last delegate result:

delegate int MyDelegate();
event MyDelegate d;

d  = () => 3;
d  = () => 1;
d  = () => 2;

var t = d.Invoke(); // t = 2

So in the original case with tasks, the last added delegate's task is returned.

  • Related