public static Task Run(Func<Task> function); - c#

Can anybody provide any examples/code snippet to use below method.
public static Task Run(Func<Task> function);
I am trying to understand how to use the above overloaded method but I did not find any code in web.
As far as I understand this method takes func delegate as input parameter which should return a Task so please provide me some code snippet.
Thanks,
Vinod

This overload is often used to offload task to a thread pool thread.
Suppose you wrote this method inside console app:
private static async Task DoSomeHeavyInitializationAsync()
{
// some heavy calculations;
// some async I/O (e.q. reading from database, file, etc);
await SomeMethodAsync(...);
// again some heavy calculations, async I/O, etc...
}
Now you want to call it from Program.Main, and keep Main responsive: if user don't want to wait app being initialized, he can press [enter] and terminate the app.
So, you need to offload task to be sure, that its code won't run on main thread. Task Run(Func<Task>) helps you:
static void Main(string[] args)
{
Task.Run(DoSomeHeavyInitializationAsync);
// do something else...
Console.ReadLine();
}

Related

Is asynchronous programming like a zombie virus?

I am experimenting with asynchronous programming in C#, mostly trying to send API calls to an API I created, but from what I understand, it is only possible to call an async method drom another async method. However, my Main method cannot be asynchronous. I don't want to have to call the method synchronously using the .Result attribute because that ruins the point of asynchronous programming. Do I have to call the method from another thread or is there another solution?
Main can now be asynchronous:
public static async Task Main(string[] args)
{
//TODO: do something more interesting
await Task.Delay(100);
}
But even when it could not be, you could take advantage of asynchronous programming just with a little boilerplate code:
public static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
}
private static async Task MainAsync(string[] args)
{
// TODO: do something more interesting.
await Task.Delay(100);
}
Please read this article for more information

How to call an async function synchronized without blocking the main thread?

I wrote a simple console application to test ConfigureAwait(false) for fixing the problem of calling an async function in a synchronized way. This is how I simulate an event and trying to call an async function in a sync way.
public static class Test2
{
private static EventHandler<int> _somethingEvent;
public static void Run()
{
_somethingEvent += OnSomething;
_somethingEvent(null, 10);
Console.WriteLine("fetch some other resources");
Console.ReadLine();
}
private static void OnSomething(object sender, int e)
{
Console.WriteLine($"passed value : {e}");
FakeAsync().Wait();
}
private static async Task FakeAsync()
{
await Task.Delay(2000).ConfigureAwait(false);
Console.WriteLine($"task completed");
}
}
the output of the code is like this:
passed value : 10
task completed
fetch some other resources
And when I change the OnSomething function to async void like this:
private static async void OnSomething(object sender, int e)
{
Console.WriteLine($"passed value : {e}");
await FakeAsync();
}
The output will change to this:
passed value : 10
fetch some other resources
task completed
You can see fetch some other resources is occurred before task completed section and this is my desired result.
My question is how can I achieve the same result by calling the async function synchronized like the first signature I wrote for the OnSomething function?
How could I use ConfigureAwait(false) to help me in this situation? Or maybe I am not using it properly.
I wrote a simple console application to test ConfigureAwait(false) for fixing the problem of calling an async function in a synchronized way.
There's a couple of problems with this.
ConfigureAwait(false) is not a "fix" for the "problem" of calling an asynchronous function synchronously. It is one possible hack that works in some situations, but it's not generally recommended because you have to use ConfigureAwait(false) everywhere in the entire transitive closure of that function - including second- and third-party calls - and if you just miss one, there is still the possibility of a deadlock. The best solution for the problem of calling an asynchronous function from a synchronous function is to change the calling function to be asynchronous (go "async all the way"). Sometimes this isn't possible and you need a hack, but there is no hack that works in every scenario.
The deadlock issue you're trying to avoid has two ingredients: blocking a thread on a task, and a single-threaded context. Console applications do not have a single-threaded context, so in a Console application it's as though all your code uses ConfigureAwait(false) everywhere.
My question is how can I achieve the same result by calling the async function synchronized like the first signature I wrote for the OnSomething function?
The calling code will either block on the asynchronous code (e.g., Wait), or it will not (e.g., await). You can't block on the asynchronous code and continue executing. The calling thread must either continue executing or block; it can't do both.
It's because when you call _somethingEvent(null, 10);, OnSomething isn't being awaited, so the following Console.WriteLine("fetch some other resources"); will be allowed to run straight after await FakeAsync(); is executed.
If you don't need to await the completion of OnSomething before continuing, just do a fire and forget:
private static void OnSomething(object sender, int e)
{
Console.WriteLine($"passed value : {e}");
Task.Run(() => FakeAsync());
}

Task and asynchronous in Console program

I have just read about special cases in console projects. Could you tell me whether my approach is right. Two jobs there i am not sure whether i should just use await inside Task.Run as i did here, if it is correct can you explain what would be the diffrence if i would delete both awaits from here. Next question what if i would remove .Wait() from WhenAny. Generally is it correct approach in console apps? Forget about proposing async Main so far, let's talk with void.
public class Program
{
public static void Main()
{
//jobs can work in parael not blocking program
var job0 = Task.Run(async () => await new DoThisAsync().Run());
var job1 = Task.Run(async () => await new DoThatAsync().Run());
//Any Independent synchronous work can run meantime jobs
IndependentSynchronousMethod;
//We wait on tasks
Task.WhenAll(job0, job1).Wait();
}
}
Most of this code was not needed
Also if you make your Main async you can do the following
public static async Task Main()
{
var job0 = DoThisAsync();
var job1 = DoThatAsync();
//Any Independent synchronous work can run meantime jobs
IndependentSynchronousMethod;
//We wait on tasks
await Task.WhenAll(job0, job1)
}
To make your Main async
Project -> Build -> Advanced - Language Version >= 7.1
Additional Resources
Task.WhenAll Method
Creates a task that will complete when all of the supplied tasks have
completed.
Can't specify the 'async' modifier on the 'Main' method of a console app
Update
Arie : to make this clear forget about async Main
With no async signature you could do this in a console app.
Task.WhenAll(job0, job1).Wait();
Your code was just wrong and wouldn't compile. However besides that, you were trying to wrap async calls in a task, which is redundant in this case. You are trying to create a task to run a task and its just not needed.
The async signature returns a task by default, Just pass them to WhenAll
If i just call Task.WhenAll(job0, job1) without Wait at the end
program would end before waiting?
Calling an async method returns a task that has already been started. So there is no actual code necessary to force it to run. However, because the task is started something needs to wait for it some how, or in the example the process will end
Task.WhenAll aggregates the tasks, it doesn't start them for you, however if you don't wait for it, or await it, it its self just lets control flow through to the exit of the application

Main Thread terminates before Task thread completion

Hi i need your help guys,
i declared new Task inside my main method like this:
static void Main(string[] args)
{
Task firstTask = Task.Factory.StartNew(()getPackage(packageId));
Task secondTask=firstTask.ContinueWith((_=>UpdatePackage(myPackage)));
}
My problem is, the main thread terminates before my task completes its action.
How should I wait Task to complete its action before terminating the main thread?
Add the following code to make your main thread block until you hit enter in the command window.
Console.Readline();
UPDATE:
If you want a non-interactive solution, then you could just wait for all the tasks to complete.
Task.WaitAll(firstTask, secondTask);
You can use an alternate paradigm for dealing with this.
static void Main(string[] args)
{
MainAsync().Wait();
}
static async Task MainAsync()
{
Task firstTask = new Task(()=>getPackage(packageId));
firstTask.ContinueWith(()=>UpdatePackage(myPackage)));
await firstTask.Run();
}
Be careful with mixing asynchronous and synchronous code like this, but, for your purposes, this should work fine (if this were winforms or WPF, you might have to worry about messaging to the UI thread, but that's not relevant here.
Assign your task to a Thread and then in your main call the .Join() function of the created thread (after it has been started of course). That way the application will wait until the task is over before ending.
This solution is more complexe than a Console.ReadLine but allows you to leave when the ask is over not before and not after.

Console App Terminating Before async Call Completion

I'm currently writing a C# console app that generates a number of URLs that point to different images on a web site and then downloads as byte streams using WebClient.DownloadDataAsync().
My issue is that once the first asynchronous call is made, the console app considers the program to be completed and terminates before the asynchronous call can return. By using a Console.Read() I can force the console to stay open but this doesn't seem like very good design. Furthermore if the user hits enter during the process (while the console is waiting for input) the program will terminate.
Is there a better way to prevent the console from closing while I am waiting for an asynchronous call to return?
Edit: the calls are asynchronous because I am providing a status indicator via the console to the user while the downloads take place.
Yes. Use a ManualResetEvent, and have the async callback call event.Set(). If the Main routine blocks on event.WaitOne(), it won't exit until the async code completes.
The basic pseudo-code would look like:
static ManualResetEvent resetEvent = new ManualResetEvent(false);
static void Main()
{
CallAsyncMethod();
resetEvent.WaitOne(); // Blocks until "set"
}
void DownloadDataCallback()
{
// Do your processing on completion...
resetEvent.Set(); // Allow the program to exit
}
Another option is to just call an async Main method and wait on the task returned.
static void Main(string[] args)
{
MainAsync(args).Wait();
}
static async Task MainAsync(string[] args)
{
// .. code goes here
}
Since .NET 4.5 you can now call GetAwaiter().GetResult()
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
}
What is the difference between .Wait() vs .GetAwaiter().GetResult()?
If that is all your application is doing, I would suggest leaving out the async call; you specifically want the app to 'hang' until the download is complete, so using an async operation is contrary to what you want here, especially in a console app.
It should be stated that in C# 7.1 Main can now be marked as async.
static async Task Main()
{
await LongRunningOperation();
}

Categories

Resources