Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simplest way to do a fire and forget method in c# 4.0

I really like this question:

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

I just want to know that now that we have Parallel extensions in C# 4.0 is there a better cleaner way to do Fire & Forget with Parallel linq?

like image 733
Jonathon Kresner Avatar asked Apr 10 '11 18:04

Jonathon Kresner


People also ask

What is a fire and forget method?

Often in application development you want a process to call another thread and continue the process flow, without waiting for a response from the called thread. This pattern is called the “fire and forget” pattern.

Can I use async without await C#?

C# Language Async-Await Returning a Task without awaitMethods that perform asynchronous operations don't need to use await if: There is only one asynchronous call inside the method. The asynchronous call is at the end of the method. Catching/handling exception that may happen within the Task is not necessary.

What does Task run do C#?

The Run method allows you to create and execute a task in a single method call and is a simpler alternative to the StartNew method. It creates a task with the following default values: Its cancellation token is CancellationToken.


2 Answers

Not an answer for 4.0, but worth noting that in .Net 4.5 you can make this even simpler with:

#pragma warning disable 4014 Task.Run(() => {     MyFireAndForgetMethod(); }).ConfigureAwait(false); #pragma warning restore 4014 

The pragma is to disable the warning that tells you you're running this Task as fire and forget.

If the method inside the curly braces returns a Task:

#pragma warning disable 4014 Task.Run(async () => {     await MyFireAndForgetMethod(); }).ConfigureAwait(false); #pragma warning restore 4014 

Let's break that down:

Task.Run returns a Task, which generates a compiler warning (warning CS4014) noting that this code will be run in the background - that's exactly what you wanted, so we disable warning 4014.

By default, Tasks attempt to "Marshal back onto the original Thread," which means that this Task will run in the background, then attempt to return to the Thread that started it. Often fire and forget Tasks finish after the original Thread is done. That will cause a ThreadAbortException to be thrown. In most cases this is harmless - it's just telling you, I tried to rejoin, I failed, but you don't care anyway. But it's still a bit noisy to have ThreadAbortExceptions either in your logs in Production, or in your debugger in local dev. .ConfigureAwait(false) is just a way of staying tidy and explicitly say, run this in the background, and that's it.

Since this is wordy, especially the ugly pragma, I use a library method for this:

public static class TaskHelper {     /// <summary>     /// Runs a TPL Task fire-and-forget style, the right way - in the     /// background, separate from the current thread, with no risk     /// of it trying to rejoin the current thread.     /// </summary>     public static void RunBg(Func<Task> fn)     {         Task.Run(fn).ConfigureAwait(false);     }      /// <summary>     /// Runs a task fire-and-forget style and notifies the TPL that this     /// will not need a Thread to resume on for a long time, or that there     /// are multiple gaps in thread use that may be long.     /// Use for example when talking to a slow webservice.     /// </summary>     public static void RunBgLong(Func<Task> fn)     {         Task.Factory.StartNew(fn, TaskCreationOptions.LongRunning)             .ConfigureAwait(false);     } } 

Usage:

TaskHelper.RunBg(async () => {     await doSomethingAsync(); } 
like image 126
Chris Moschini Avatar answered Oct 07 '22 09:10

Chris Moschini


With the Task class yes, but PLINQ is really for querying over collections.

Something like the following will do it with Task.

Task.Factory.StartNew(() => FireAway()); 

Or even...

Task.Factory.StartNew(FireAway); 

Or...

new Task(FireAway).Start(); 

Where FireAway is

public static void FireAway() {     // Blah... } 

So by virtue of class and method name terseness this beats the threadpool version by between six and nineteen characters depending on the one you choose :)

ThreadPool.QueueUserWorkItem(o => FireAway()); 
like image 28
Ade Miller Avatar answered Oct 07 '22 10:10

Ade Miller