Simplest Way to Do a Fire and Forget Method in C# 4.0

Simplest way to do a fire and forget method in C#?

ThreadPool.QueueUserWorkItem(o => FireAway());

(five years later...)

Task.Run(() => FireAway());

as pointed out by luisperezphd.

Fire and Forget multiple methods in C#

As you're using an Azure function you cannot have true fire and forget as you risk the function terminating before the completion of all the task(s).

However, we don't care for the result of the task, so we need not await each task individually.

System.Collections.Generic.List<System.Threading.Tasks.Task> tasks = new System.Collections.Generic.List<System.Threading.Tasks.Task>();
for (int i = 0; i < 20; i++)
{
tasks.Add(System.Threading.Tasks.Task.Run(() => ApiRef1(i, log));
}
await System.Threading.Tasks.Task.WhenAll(tasks);

This allows all the tasks to fire in parallel, but pause further execution until they're all complete, ensuring the completion of the tasks before the process is terminated.

Fire & Forget method using Task.Run not working

HttpContext will not be available in threads other than the main thread, so you can't depend on it.

But you can pass data from HttpContext to your method when you start the task. For example:

Task.Run(() => MyClass.doWork(HttpContext.Current.Session["somedata"])).ConfigureAwait(false);

Fire and forget, using `Task.Run` or just calling an async method without `await`

In general especially when it comes to libraries or console apps, in order to fire and forget an async method, is it better to just call the async method without awaiting it or use Task.Run?

In general, it's best not to use fire-and-forget at all.

"Fire and forget" means:

  1. You don't care if the code has an exception. Any exceptions will cause it to fail silently; no logging, no notification, etc.
  2. You don't need to know when the code completes. I.e., the consuming application doesn't ever need to wait for the code to complete. Even during shutdown.
  3. You don't need the code to complete. As a corollary of (2), fire-and-forget code may not run to completion; and as a corollary of (1), you would have no notification that it failed to complete.

In short, "fire and forget" is only appropriate for an extremely small number of tasks. E.g., updating a cache. I'd say probably 85% or more of "fire and forget" code is wrong - it's using fire and forget for code that should not be fire and forget.

So I'd say the best solution is to not use fire and forget at all. At the very least, you should expose a Task somewhere that represents a "followup action". Consider adding the Task to your return type or exposing it as a property.

Adopting fire and forget - especially in a library - means you're forcing all consumers to never know when it's safe to shut down and exit. But if you really want to do fire and forget, there are a few options.

A. One option is calling an async void function without a context. The consuming application still has no way to determine if/when the code completes, but at least that way exceptions are not ignored.

B. Another option is to start the task without a context. This option has both disadvantages of fire and forget code: exceptions are ignored and the calling code cannot know when it completes.

Both of these recommendations start the task without a context. There are helpers for doing this, or you can wrap the call in Task.Run (slightly less efficient, but it works fine).

I wouldn't recommend starting the task directly. While this would work fine in a Console app, it's not appropriate for libraries which may be called in situations where a context is provided.

Fire and Forget (but not completely)

I'd use the ActionBlock of the TPL Dataflow (See http://blog.stephencleary.com/2012/09/introduction-to-dataflow-part-2.html for an intro)

It's a NuGet package, so see if it fits your framework version requirements.

static void Main(string[] args)
{
var a = new ActionBlock<int>(async (messageNumber) =>
{
await Task.Delay(messageNumber * 1000);
Console.WriteLine(messageNumber);
});

a.Post(5);
Console.WriteLine("5 sent");

a.Post(2);
Console.WriteLine("2 sent");

a.Post(1);
Console.WriteLine("1 sent");

a.Post(4);
Console.WriteLine("4 sent");

Console.WriteLine("all sent");
Console.ReadLine();
}

It will be processed in a fire-and-forget manner in the order it has been posted to the ActionBlock.

Output:

5 sent
2 sent
1 sent
4 sent
all sent
5
2
1
4

Proper way to start and async fire-and-forget call?

It depends on what you mean by proper :)

For instance: are you interested in the exceptions being thrown in your "fire and forget" calls? If not, than this is sort of fine. Though what you might need to think about is in what environment the task lives.

For instance, if this is a asp.net application and you do this inside the lifetime of a thread instantiated due to a call to a .aspx or .svc. The Task becomes a background thread of that (foreground)thread. The foreground thread might get cleaned up by the application pool before your "fire and forget" task is completed.

So also think about in which thread your tasks live.

I think this article gives you some useful information on that:
https://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx

Also note that if you do not return a value in your Tasks, a task will not return exception info. Source for that is the ref book for microsoft exam 70-483
There is probably a free version of that online somewhere ;P https://www.amazon.com/Exam-Ref-70-483-Programming-C/dp/0735676828

Maybe useful to know is that if your have an async method being called by a non-async and you wish to know its result. You can use .GetAwaiter().GetResult().

Also I think it is important to note the difference between async and multi-threading.

Async is only useful if there are operations that use other parts of a computer that is not the CPU. So things like networking or I/O operations. Using async then tells the system to go ahead and use CPU power somewhere else instead of "blocking" that thread in the CPU for just waiting for a response.

multi-threading is the allocation of operations on different threads in a CPU (for instance, creating a task which creates a background thread of the foreground thread... foreground threads being the threads that make up your application, they are primary, background threads exist linked to foreground threads. If you close the linked foreground thread, the background thread closes as well)
This allows the CPU to work on different tasks at the same time.

Combining these two makes sure the CPU does not get blocked up on just 4 threads if it is a 4 thread CPU. But can open more while it waits for async tasks that are waiting for I/O operations.

I hope this gives your the information needed to do, what ever it is you are doing :)



Related Topics



Leave a reply



Submit