1

When I call an async method which returns void, is it the same as when I invoke it with the Task.Run method? I ask because in the doc of the FileSystemWatcher they mention the following.

Keep your event handling code as short as possible.

https://learn.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher?view=net-5.0#events-and-buffer-sizes

So I want to leave the scope of the event method very fast. Or do they mean something different?

Snippet of my code for better understanding.

private void OnCreated(object sender, FileSystemEventArgs e)
{
    RunSaveWithLogger(AddLocation, e.FullPath);
}

private async void RunSaveWithLogger(Func<string, Task> func, string fullPath)
{

Edit:

After reading your answers and comments, I changed my code to this.

private void OnCreated(object sender, FileSystemEventArgs e)
{
    Task.Run(() =>
    {
        RunSaveWithLogger(AddLocation, e.FullPath);
    });
}

private async void RunSaveWithLogger(Func<string, Task> func, string fullPath)
{
    try
    {
        await func.Invoke(fullPath);
    }
    catch (Exception exception)
    {
        _logger.LogError(exception, "");
    }
}

Thanks for your time and help, I really appreciate that.

Master Silver
  • 99
  • 1
  • 6
  • [Stephen Cleary](https://stackoverflow.com/questions/18013523/when-correctly-use-task-run-and-when-just-async-await) explains this well there and [at his blog](http://blog.stephencleary.com/2013/04/ui-guidelines-for-async.html) as well. – Trevor May 12 '21 at 18:01
  • 3
    Honestly: never ever write `async void` unless you absolutely cannot help it. This isn't hyperbole - there are scenarios where that by itself is enough to cause failure at runtime (they are complex, and have to do with sync-context implementation choices in different frameworks). But no, they're not even remotely similar. An `async void` method can quite happily run to completion blocking the current thread; it isn't *required* to go fully async at any point – Marc Gravell May 12 '21 at 18:13
  • 1
    `Task.Run()` is a _mechanism_ for introducing asynchrony, while `async` is a syntactical way of expressing (and enabling) the intent to do so. The two are very much _not_ the same. See duplicate for a detailed explanation as well as links to additional references describing how the two relate. Note that `async void` is just a special case of `async`, and one which should be avoided except for event handlers where the `void` return type is required (and even then, make very sure you handle exceptions there, because no other observer will be able to). – Peter Duniho May 12 '21 at 18:17
  • 1
    You can find [here](https://stackoverflow.com/questions/66258633/filesystemwatcher-not-working-even-once-except-for-root-folder-having-320k-subdi/66293976#66293976) an `Offload` method that offloads explicitly the event handlers to the `ThreadPool`. But your `async void` approach is also valid. The [`async void`](https://docs.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming#avoid-async-void) is intended for event handlers, and your `RunSaveWithLogger` method seems like a thin wrapper of an event handler, so I would say it's OK. – Theodor Zoulias May 12 '21 at 19:40
  • 2
    "Honestly: never ever write async void unless you absolutely cannot help it. This isn't hyperbole". Hyperbole is exactly what it is. There are totally legitimate reasons to use `async void`. In some cases it is actually preferable to `Task.Run`. If this question hadn't been closed like 99% of new questions on SO I'd go into more detail. – Emperor Eto May 14 '21 at 12:50

1 Answers1

1

simple answer No! they are not the same. for instance, in the example below, "Task.Run" creates a new thread and so, runs every code within it in a new thread, while "async void" doesn't. (I doubt if this is the answer you are looking for though).

using System;
using System.Threading.Tasks;
class Solution
{
    static void Main(string[] args)
    {
        async void Method1()
        {
            while (true)
            {

            }
        }
        Task.Run(() => {
            while (true)
            {

            }
        });
        Console.WriteLine("This  will print");
        Method1();
        Console.WriteLine("This won't");
    }
}
  • 1
    ""Task.Run" creates a new thread". It actually does not create a new thread. It executes the code on a thread from the thread pool, which is likely (if not guaranteed?) to be a different thread than the calling thread. I realize for most people this distinction doesn't matter, but it can. Meanwhile `async void` may or may not run on the calling thread. So they do accomplish very similar things and often (but not always) lead to the same result. – Emperor Eto May 14 '21 at 12:48