I am writing a MVC5 app that has a controller with a function say Method1
I have a third party function that is async Task
, let's call it DoMethodAsync
(it essentially makes a POST call).
I want to call it right before returning from Method1
but I don't really care about the result of the async task, if it fails, it fails. How can I fire and forget and have it execute in the background so that it does not block the controller from responding to other requests?
How can I ensure that DoMethodAsync
is only executed after Method1
has returned?
C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.
What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.
C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.
I don't really care about the result of the async task, if it fails, it fails.
Really? Just asking, because this is an extremely rare use case.
How can I fire and forget and have it execute in the background so that it does not block the controller from responding to other requests?
I have a blog post that looks into various approaches to "fire and forget" tasks on ASP.NET.
You don't want to just call the method and ignore the returned task, because that method will inherit the request context for the initiating request. Then after the request is completed, the request context is disposed, and that method can end up in an "interesting" place - some things will work, but others will not.
So, the minimum viable solution is to wrap it in Task.Run
:
var _ignored = Task.Run(() => DoMethodAsync());
However, note that ASP.NET is completely unaware of this "extra operation". If you want DoMethodAsync
to have more of a chance of actually executing to completion, then you'll want to register it with the ASP.NET runtime, either using HostingEnvironment.QueueBackgroundWorkItem
(4.5.2+) or my own BackgroundTaskManager.Run
(4.5.0/4.5.1).
Also note that none of these options will guarantee that DoMethodAsync
will run to completion; they just give you a "best effort." For a truly reliable system, you'd need a proper distributed architecture, i.e., reliable storage with an independent processor.
I know this is old, but after hours of searching and trying different things myself, I came across this thread. Combining some info here with other resource, I was able to implement what I wanted which I believe is the same thing the OP wanted.
I wanted to call a URL like /API/Start and I wanted that URL to instantly return a view that said "Thank you for starting, check back later". However it needed to then simply kick off a background job.
This is with MVC 5 so not sure if it makes a difference, but...
Side Note: To see this in action, use 2 URL's /Default/Index <-- will report back ~5 seconds /Default/IndexAsync <-- will report back ~0 seconds (well sort of .. you'll see)
public class DefaultController : Controller
{
// GET: Sync
public ActionResult Index()
{
System.Diagnostics.Stopwatch myStopwatch = new System.Diagnostics.Stopwatch();
myStopwatch.Start();
DoTask();
myStopwatch.Stop();
ViewBag.Message = ($"Process took {myStopwatch.Elapsed.TotalSeconds.ToString()}");
return View("Index");
}
// GET: Async
public ActionResult IndexAsync()
{
System.Diagnostics.Stopwatch myStopwatch = new System.Diagnostics.Stopwatch();
myStopwatch.Start();
Task.Factory.StartNew(DoTaskAsync);
myStopwatch.Stop();
ViewBag.Message = ($"Process took {myStopwatch.Elapsed.TotalSeconds.ToString()}");
return View("Index");
}
// "the Sync Task"
private void DoTask()
{
System.Diagnostics.Debug.Print($"DoTask Started at {DateTime.Now.ToString()}");
System.Threading.Thread.Sleep(5000);
System.Diagnostics.Debug.Print($"DoTask Finished at {DateTime.Now.ToString()}");
}
// "the Async Task"
private async Task DoTaskAsync()
{
System.Diagnostics.Debug.Print($"DoTaskAsync Started at {DateTime.Now.ToString()}");
System.Threading.Thread.Sleep(5000);
System.Diagnostics.Debug.Print($"DoTaskAsync Finished at {DateTime.Now.ToString()}");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With