I've been reading the following post, specifically this point:
On your application’s entry point method, e.g. Main. When you await an instance that’s not yet completed, execution returns to the caller of the method. In the case of Main, this would return out of Main, effectively ending the program.
I've been trying to do that, but I can't seem to make it exit. Here's the code I have:
class Program
{
// ending main!!!
static async Task Main(string[] args)
{
Task<Task<string>> t = new Task<Task<string>>(async () =>
{
Console.WriteLine("Synchronous");
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Synchronous");
Console.WriteLine("Synchronous I is: " + i);
await Task.Run(() => { Console.WriteLine("Asynchronous"); });
await Task.Run(() => { for (int j = 0; j < 1000; j++) { Console.WriteLine( "Asynchronous, program should have exited by now?"); }});
}
return "ASD";
});
t.Start();
await t;
}
}
What exactly am I missing here? Shouldn't the program exit upon hitting the line await t; or by following through the thread at await Task.Run(() => { Console.WriteLine("Asynchronous"); });?
This is a Console application's main method.
The article you linked is from 2012, which predates the addition of async support to Main(), which is why what it's talking about seems wrong.
For the current implementation, consider the following code:
public static async Task Main()
{
Console.WriteLine("Awaiting");
await Task.Delay(2000);
Console.WriteLine("Awaited");
}
This gets converted by the compiler as follows (I used "JustDecompile" to decompile this):
private static void <Main>()
{
Program.Main().GetAwaiter().GetResult();
}
public static async Task Main()
{
Console.WriteLine("Awaiting");
await Task.Delay(2000);
Console.WriteLine("Awaited");
}
Now you can see why the program doesn't exit.
The async Task Main() gets called from static void <Main>() which waits for the Task returned from async Task Main() to complete (by accessing .GetResult()) before the program exits.
Related
I have a simple program to test async/await, 2 versions: version 1 awaits another method inside async function, version doesn't:
Program 1:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("main starts..");
AsyncMethod();
Thread.Sleep(1000);
Console.WriteLine("main ends..");
Console.ReadLine();
}
static async void AsyncMethod()
{
Console.WriteLine("async starts");
var result = await MyMethod();
Console.WriteLine("async starts ends");
}
static async Task<int> MyMethod()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("async runs" + i.ToString() + "..");
await Task.Delay(1000);
}
return 0;
}
}
Program 2:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("main starts..");
AsyncMethod();
Thread.Sleep(1000);
Console.WriteLine("main ends..");
Console.ReadLine();
}
static async void AsyncMethod()
{
Console.WriteLine("async starts");
for (int i = 0; i < 5; i++)
{
Console.WriteLine("async runs" + i.ToString() + "..");
await Task.Delay(1000);
}
Console.WriteLine("async ends");
}
}
Both programs yields same result. I am just curious, do both program differs in what happens in the background?
I guess, program 1 will create 2 sub-threads, each level of "async" leads to a thread; program 2 will create 1 sub-thread. Right?
As long as "await" will wait until the task ends, then what's the difference from writing synchronous code? I think it just link creating several threads and call ".join()" for all of them. Right?
Both are async or Threaded programming using await means until your function execute your execution pointer will be hold on that functions it self and if you don't use wait it will pass on to next execution pointer mostly there is two reason behind adding await mostly in winform application while going for big process execution we may need to let software user to do the other work in the same form then we need to await the task. or some times we need get some data from one method so the method should be finished and next logic should execute in a new or other thread.
I'm puzzled with this situation, where a class has a method that launches two periodic Tasks and then a property is used to check if both Tasks are still running or not, but the result is unexpected. Here is the code (simplified):
public partial class UdpClientConnector
{
Task localListener;
Task periodicSubscriber;
bool keepWorking = false;
public bool IsRunning
{
get
{
if ((localListener != null) && (periodicSubscriber != null))
{
return (localListener.Status == TaskStatus.Running) &&
(periodicSubscriber.Status == TaskStatus.Running);
}
else
return false;
}
}
public void Start()
{
keepWorking = true;
localListener = new Task(() => LocalListenerWorker());
localListener.Start();
periodicSubscriber = new Task(() => PeriodicSubscriberWorker());
periodicSubscriber.Start();
}
public void Stop()
{
keepWorking = false;
localListener.Wait();
periodicSubscriber.Wait();
}
async void LocalListenerWorker()
{
while (keepWorking)
{
// Do some work and then wait a bit
await Task.Delay(1000);
}
}
async void PeriodicSubscriberWorker()
{
while (keepWorking)
{
// Do some (other) work and then wait a bit
await Task.Delay(1000);
}
}
}
To test this boilerplate I used the following:
UdpClientConnector connector = new UdpClientConnector();
// This assert is successful because the two Tasks are not yet started
Assert.IsTrue(!connector.IsRunning);
// Starts the tasks and wait a bit
Connector.Start();
Task.Delay(2000).Wait();
// This fails
Assert.IsTrue(connector.IsRunning);
When I've tried to debug the test case, I've found that two Tasks are in the RanToCompletion state, which is unexpected due the fact that both tasks are just loops and should not terminate until keepWorking becomes false.
I've tried also to start the Tasks using Task.Factory.StartNew(..) with same results.
What I'm missing? Thank you!
The problem is with how you start the tasks, and indeed the task methods.
localListener = new Task(() => LocalListenerWorker());
That task will complete when LocalListenerWorker returns - which it will do pretty much immediately (when it hits the first await expression). It doesn't wait for the asynchronous operation to actually complete (i.e. the loop to finish).
async void methods should almost never be used - they're basically only there to support event handlers.
I suggest you rewrite your methods to return Task, and then use Task.Run to start them, passing in a method group:
Task.Run(LocalListenerWorker);
...
private async Task LocalListenerWorker()
{
// Body as before
}
The task by Task.Run will only complete when the task returned by LocalListenerWorker completes, which is when the loop body finishes.
Here's a complete demo:
using System;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
Task task1 = Task.Run(Loop);
// Don't do this normally! It's just as a simple demo
// in a console app...
task1.Wait();
Console.WriteLine("First task done");
Task task2 = new Task(() => Broken());
task2.Start();
// Don't do this normally! It's just as a simple demo
// in a console app...
task2.Wait();
Console.WriteLine("Second task done");
}
static async Task Loop()
{
for (int i = 0; i < 5; i++)
{
await Task.Delay(1000);
Console.WriteLine(i);
}
}
static async void Broken()
{
for (int i = 0; i < 5; i++)
{
await Task.Delay(1000);
Console.WriteLine(i);
}
}
}
The output shows:
0
1
2
3
4
First task done
Second task done
The first task behaves as expected, and only completes when the first async method has really completed. The second task behaves like your current code: it completes as soon as the second async method has returned - which happens almost immediately due to the await.
This question already has answers here:
Can't specify the 'async' modifier on the 'Main' method of a console app
(20 answers)
Closed 5 years ago.
I have this simple code:
public static async Task<int> SumTwoOperationsAsync()
{
var firstTask = GetOperationOneAsync();
var secondTask = GetOperationTwoAsync();
return await firstTask + await secondTask;
}
private async Task<int> GetOperationOneAsync()
{
await Task.Delay(500); // Just to simulate an operation taking time
return 10;
}
private async Task<int> GetOperationTwoAsync()
{
await Task.Delay(100); // Just to simulate an operation taking time
return 5;
}
Great. This compiles.
But let’s say I have a console application and I want to run the code above (calling SumTwoOperationsAsync()).
static void Main(string[] args)
{
SumTwoOperationsAsync();
}
But I've read that (when using sync) I have to sync all the way up and down:
Does this mean that my Main function should be marked as async?
Well, it can't be because there is a compilation error:
an entry point cannot be marked with the 'async' modifier
If I understand the async stuff , the thread will enter the Main function → SumTwoOperationsAsync → will call both functions and will be out. But until the SumTwoOperationsAsync
What am I missing?
In most project types, your async "up" and "down" will end at an async void event handler or returning a Task to your framework.
However, Console apps do not support this.
You can either just do a Wait on the returned task:
static void Main()
{
MainAsync().Wait();
// or, if you want to avoid exceptions being wrapped into AggregateException:
// MainAsync().GetAwaiter().GetResult();
}
static async Task MainAsync()
{
...
}
or you can use your own context like the one I wrote:
static void Main()
{
AsyncContext.Run(() => MainAsync());
}
static async Task MainAsync()
{
...
}
More information for async Console apps is on my blog.
Here is the simplest way to do this
static void Main(string[] args)
{
Task t = MainAsync(args);
t.Wait();
}
static async Task MainAsync(string[] args)
{
await ...
}
As a quick and very scoped solution:
Task.Result
Both Task.Result and Task.Wait won't allow to improving scalability when used with I/O, as they will cause the calling thread to stay blocked waiting for the I/O to end.
When you call .Result on an incomplete Task, the thread executing the method has to sit and wait for the task to complete, which blocks the thread from doing any other useful work in the meantime. This negates the benefit of the asynchronous nature of the task.
notasync
My solution. The JSONServer is a class I wrote for running an HttpListener server in a console window.
class Program
{
public static JSONServer srv = null;
static void Main(string[] args)
{
Console.WriteLine("NLPS Core Server");
srv = new JSONServer(100);
srv.Start();
InputLoopProcessor();
while(srv.IsRunning)
{
Thread.Sleep(250);
}
}
private static async Task InputLoopProcessor()
{
string line = "";
Console.WriteLine("Core NLPS Server: Started on port 8080. " + DateTime.Now);
while(line != "quit")
{
Console.Write(": ");
line = Console.ReadLine().ToLower();
Console.WriteLine(line);
if(line == "?" || line == "help")
{
Console.WriteLine("Core NLPS Server Help");
Console.WriteLine(" ? or help: Show this help.");
Console.WriteLine(" quit: Stop the server.");
}
}
srv.Stop();
Console.WriteLine("Core Processor done at " + DateTime.Now);
}
}
I have searched a lot of codes saying that is possible to use multiple cores with parallel async, but none worked. It is always stuck in a single core.
Is it possible?
This is uses 100% of the cpu:
class Program
{
static void Main(string[] args)
{
Parallel.For(0, 100000, p =>
{
while (true) { }
});
}
}
Using parallel async, I dont get more than 12%:
class Program
{
static void Main(string[] args)
{
Task.Run(async () =>
{
var tasks = Enumerable.Range(0, 1000000).Select(i =>
{
while (true) { }
return Task.FromResult(0);
});
await Task.WhenAll(tasks);
}).GetAwaiter().GetResult();
}
}
100% cpu. Thanks all that helped, and not just mocked or tried to close:
class Program
{
static void Main(string[] args)
{
Task.Run(async () =>
{
var tasks = new List<Task>();
for (int i = 0; i < 100; i++)
tasks.Add(Task.Run(() =>
{
while (true) { }
}));
await Task.WhenAll(tasks);
}).GetAwaiter().GetResult();
}
}
Your code only creates one task, Task.FromResult returns a finished task and it's added after the while loop, that will be executed 100000 times, but one after other as the generation is done by the synchronous function Select.
You can change your code to this:
class Program
{
static void Main(string[] args)
{
var tasks = Enumerable.Range(0, 1000000).Select(i =>
{
return Task.Run(() =>
{
while (true) { }
return 0;
});
});
Task.WhenAll(tasks).GetAwaiter().GetResult();
}
}
It will use the 100%, tested.
When WhenAll goes to get the first task, it'll ask your query, task, for the first task. It will use the selector to try to translate the first result of Range (0), into a Task. Since your selector has an infinite loop, that will never return. The only work that ever happens is sitting waiting for the first task to be generated, when it never will be.
Other than that your main thread does nothing but ask a thread pool thread to do all the things, you never create any additional threads, and thus have no oppertunity to use multiple cores on your CPU.
using System;
using System.Threading.Tasks;
namespace _1._8_Starting_A_New_Task
{
public static class Program
{
public static void Main()
{
Task t = new Task(() =>
{
for (int x = 0; x < 100; x++)
{
Console.Write('*');
}
});
t.Wait();
}
}
}
This application compiles and runs displaying a blank screen (waiting on the task to complete)
The task stays in a waiting state
No output is displayed/written to console
Why not?
Application stays in "wait" state permanently
Why?
Goal of code: Start a new task, wait for task to complete, exit application
Because you never start the Task. Using the Task constructor requires you to call Task.Start on the returned task. This is why it's recommended to use Task.Run instead, which returns a "Hot task" (a task which has started):
The documentation:
Rather than calling this constructor, the most common way to
instantiate a Task object and launch a task is by calling the static
Task.Run(Action) or TaskFactory.StartNew(Action) method. The only
advantage offered by this constructor is that it allows object
instantiation to be separated from task invocation.
So the code should be:
public static void Main()
{
Task t = Task.Run(() =>
{
for (int x = 0; x < 100; x++)
{
Console.Write('*');
}
});
t.Wait();
}