8

I used to call async methods (fire and forgot?) in constructors by

 Task.Run(async () => await CallAsync());

I heard it's better to use ICommand to execute it.

ICommand MyCmd => new Command(async () => await CallAsync());

public MyClass()
{
     MyCmd.Execute(null);
}

What's the difference between these two methods?

R15
  • 13,982
  • 14
  • 97
  • 173
ca9163d9
  • 27,283
  • 64
  • 210
  • 413
  • 5
    You shouldnt perform any processing in constructors in the first place – FCin Nov 21 '18 at 05:31
  • 1
    `HostingEnvironment.QueueBackgroundWorkItem` is recommended mostly, take a look at here https://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html – Just code Nov 21 '18 at 05:34
  • @FCin, it says initializing the WinForms controls in the constructor can be much faster in this question, https://stackoverflow.com/questions/2521322/what-setup-code-should-go-in-form-constructors-versus-form-load-event. – ca9163d9 Nov 21 '18 at 06:11
  • This refers to updating controls. I'm talking about processing/retrieving data which I assume you do, because you clearly await something. Also, you haven't tagged your question with what framework you are using. WinForms I assume? – FCin Nov 21 '18 at 06:21
  • @FCin, the async method calls methods which read database asynchronously and initialize the controls with the data. – ca9163d9 Nov 21 '18 at 06:25
  • 1
    You've mentioned WinForms and WPF... Could you please clarify what framework you are targeting? Without it looks like dup of https://stackoverflow.com/questions/21354550/async-method-which-is-called-from-constructor (or similar posts) – Alexei Levenkov Nov 21 '18 at 06:39
  • 12
    You're violating the expectation that when a constructor returns, the object is correctly initialized and ready to be used. Consider instead using a *factory* that performs the async works and passes the *results* of that work into an appropriately parameterized constructor for this class instead. That factory method can be `async`. – Damien_The_Unbeliever Nov 21 '18 at 07:08
  • For initializing forms and retrieving data a constructor is the wrong place. you should react on an event being fired – Daniel Schmid Sep 18 '19 at 12:26

2 Answers2

9

Your post makes not much sense.

If you want to fire-and-forget an async method, then just calling it directly is enough.

public Task RunAsync() { }

public Constructor()
{
    RunAsync(); // fire-and-forget by not awaiting and ignoring returned task
}

There is no need to use Task.Run or Command, which technically does nothing on top of running the method.

But this kind of fire-and-forget code is frowned upon, because it makes testing of the code difficult. And starting such code in constructor makes the object creation have unexpected side-effects that are not immediately obvious. It is recommended to have some kind of Initialize method that can be called.

Another issue is that if the method causes an exception, a special handler must be register, otherwise it crashes whole application.

Euphoric
  • 12,645
  • 1
  • 30
  • 44
-2

Task.Run(async () => await CallAsync()) can be simplified to Task.Run(CallAsync) without loss of any functionality.

A difference can relate to implementation of your Command class, but it's not shown in your question. There is no difference in the shown fragment. You can implement the Execute method to create a special set of commands.

The comment to the previous answer: 'There is no need to use Task.Run or Command, which technically does nothing on top of running the method' - this statement is not correct. 'Task.Run' creates a new thread while direct method calling doesn't.

rotabor
  • 561
  • 2
  • 10