Async And Await in C# And problems - c#

This program does not print the output in the correct order.
public static void Main(string[] args)
{
new Program().Start();
}
public async void Start()
{
int num1 = await GetNumber();
int num2 = await GetNumber();
int num3 = await GetNumber();
Console.WriteLine("Wait...");
Console.ReadKey();
}
public static async Task<int> GetNumber()
{
System.Threading.Thread.Sleep(4000);
Console.WriteLine("Hello");
return 0;
}
It outputs:
--------wait 4Seconds
--------print Hello
--------wait 4Seconds
--------print Hello
--------wait 4Seconds
--------print Hello
--------print wait....
It should output
--------print wait....
--------wait 4Seconds
--------print Hello
--------print Hello
--------print Hello

Use
Await Task.Delay(Timespan.FromMilliSeconds (4000))
instead of Thread.Sleep.
The fully worked out example.
using System;
using System.Threading.Tasks;
namespace Brad
{
public class Program
{
public static void Main(string[] args)
{
var task = new Program().Start();
Console.WriteLine("Wait...");
// You have to put a synchronous Wait() here because
// Main cannot be declared as async
task.Wait();
}
public async Task Start()
{
int num1 = await GetNumber();
int num2 = await GetNumber();
int num3 = await GetNumber();
Console.WriteLine("Finished");
}
public static async Task<int> GetNumber()
{
await Task.Delay(TimeSpan.FromMilliseconds(400));
Console.WriteLine("Hello");
return 0;
}
}
}
You can see it running here
https://dotnetfiddle.net/KHJaDZ
or maybe you wanted the tasks running in parallel instead of one after the other. You can try
using System;
using System.Threading.Tasks;
namespace Brad
{
public class Program
{
public static void Main(string[] args)
{
var task = new Program().Start();
Console.WriteLine("Wait...");
// You have to put a synchronous Wait() here because
// Main cannot be declared as async
task.Wait();
}
public async Task Start()
{
var task1 = GetNumber();
var task2 = GetNumber();
var task3 = GetNumber();
// This runs the tasks in parallel
await Task.WhenAll(task1, task2, task3);
Console.WriteLine("Finished");
}
public static async Task<int> GetNumber()
{
await Task.Delay(TimeSpan.FromMilliseconds(400));
Console.WriteLine("Hello");
return 0;
}
}
}
and this is running here.
https://dotnetfiddle.net/kVk77Z

await means "break the method in half here and come back later when this call finishes". It's how you "convert" a Task<T> into a T: by waiting for (awaiting) the task. Otherwise you are stuck with a Task<T>.
It seems like what you are looking for instead is not awaiting the tasks so that they run asynchronously, but if you did that then you wouldn't be able to get the int results.
(As the other answer mentions, you also need to await something in GetNumber or it will not actually be asynchronous.)
Something like:
public static void Main(string[] args) {
new Program().Start();
}
public void Start() {
GetNumber();
GetNumber();
GetNumber();
Console.WriteLine("Wait...");
Console.ReadKey();
}
public static async Task<int> GetNumber() {
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine("Hello");
return 0;
}
should give the output you expect:
Wait...
Hello
Hello
Hello

Related

Simple.OData.Client not returning results, no error [duplicate]

public class test
{
public async Task Go()
{
await PrintAnswerToLife();
Console.WriteLine("done");
}
public async Task PrintAnswerToLife()
{
int answer = await GetAnswerToLife();
Console.WriteLine(answer);
}
public async Task<int> GetAnswerToLife()
{
await Task.Delay(5000);
int answer = 21 * 2;
return answer;
}
}
if I want to call Go in main() method, how can I do that?
I am trying out c# new features, I know i can hook the async method to a event and by triggering that event, async method can be called.
But what if I want to call it directly in main method? How can i do that?
I did something like
class Program
{
static void Main(string[] args)
{
test t = new test();
t.Go().GetAwaiter().OnCompleted(() =>
{
Console.WriteLine("finished");
});
Console.ReadKey();
}
}
But seems it's a dead lock and nothing is printed on the screen.
Your Main method can be simplified. For C# 7.1 and newer:
static async Task Main(string[] args)
{
test t = new test();
await t.Go();
Console.WriteLine("finished");
Console.ReadKey();
}
For earlier versions of C#:
static void Main(string[] args)
{
test t = new test();
t.Go().Wait();
Console.WriteLine("finished");
Console.ReadKey();
}
This is part of the beauty of the async keyword (and related functionality): the use and confusing nature of callbacks is greatly reduced or eliminated.
Instead of Wait, you're better off using
new test().Go().GetAwaiter().GetResult()
since this will avoid exceptions being wrapped into AggregateExceptions, so you can just surround your Go() method with a try catch(Exception ex) block as usual.
Since the release of C# v7.1 async main methods have become available to use which avoids the need for the workarounds in the answers already posted. The following signatures have been added:
public static Task Main();
public static Task<int> Main();
public static Task Main(string[] args);
public static Task<int> Main(string[] args);
This allows you to write your code like this:
static async Task Main(string[] args)
{
await DoSomethingAsync();
}
static async Task DoSomethingAsync()
{
//...
}
class Program
{
static void Main(string[] args)
{
test t = new test();
Task.Run(async () => await t.Go());
}
}
As long as you are accessing the result object from the returned task, there is no need to use GetAwaiter at all (Only in case you are accessing the result).
static async Task<String> sayHelloAsync(){
await Task.Delay(1000);
return "hello world";
}
static void main(string[] args){
var data = sayHelloAsync();
//implicitly waits for the result and makes synchronous call.
//no need for Console.ReadKey()
Console.Write(data.Result);
//synchronous call .. same as previous one
Console.Write(sayHelloAsync().GetAwaiter().GetResult());
}
if you want to wait for a task to be done and do some further processing:
sayHelloAsyn().GetAwaiter().OnCompleted(() => {
Console.Write("done" );
});
Console.ReadLine();
If you are interested in getting the results from sayHelloAsync and do further processing on it:
sayHelloAsync().ContinueWith(prev => {
//prev.Result should have "hello world"
Console.Write("done do further processing here .. here is the result from sayHelloAsync" + prev.Result);
});
Console.ReadLine();
One last simple way to wait for function:
static void main(string[] args){
sayHelloAsync().Wait();
Console.Read();
}
static async Task sayHelloAsync(){
await Task.Delay(1000);
Console.Write( "hello world");
}
public static void Main(string[] args)
{
var t = new test();
Task.Run(async () => { await t.Go();}).Wait();
}
Use .Wait()
static void Main(string[] args){
SomeTaskManager someTaskManager = new SomeTaskManager();
Task<List<String>> task = Task.Run(() => marginaleNotesGenerationTask.Execute());
task.Wait();
List<String> r = task.Result;
}
public class SomeTaskManager
{
public async Task<List<String>> Execute() {
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:4000/");
client.DefaultRequestHeaders.Accept.Clear();
HttpContent httpContent = new StringContent(jsonEnvellope, Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage httpResponse = await client.PostAsync("", httpContent);
if (httpResponse.Content != null)
{
string responseContent = await httpResponse.Content.ReadAsStringAsync();
dynamic answer = JsonConvert.DeserializeObject(responseContent);
summaries = answer[0].ToObject<List<String>>();
}
}
}
try "Result" property
class Program
{
static void Main(string[] args)
{
test t = new test();
t.Go().Result;
Console.ReadKey();
}
}
C# 9 Top-level statements simplified things even more, now you don't even have to do anything extra to call async methods from your Main, you can just do this:
using System;
using System.Threading.Tasks;
await Task.Delay(1000);
Console.WriteLine("Hello World!");
For more information see What's new in C# 9.0, Top-level statements:
The top-level statements may contain async expressions. In that case, the synthesized entry point returns a Task, or Task<int>.

Proper async looping in console app

I know async I/O doesn't bring parallelism but I thought when the app is awaiting an async operation it could carry on doing other stuff.
Consider the below code I would expect the loop to carry on while awaiting Wait(i) but obviously I was wrong and each iteration is blocking. What's the correct way to achieve some concurrency here?
using System;
using System.Threading.Tasks;
namespace asynctest
{
class Program
{
static void Main(string[] args)
{
Do().GetAwaiter().GetResult();
}
public static async Task Do()
{
for(int i=0;i<10;i++)
{
await Wait(i);
}
}
public static async Task Wait(int i)
{
await Task.Delay(10000);
}
}
}
public static async Task Do()
{
var tasks = new Task[10];
for (int i = 0; i < 10; i++)
{
tasks[i] = Wait(i);
}
await Task.WhenAll(tasks);
}
You should use WhenAll() to combine the task results, thus your tasks will run in parallel:
namespace asynctest
{
class Program
{
static void Main(string[] args)
{
Do().GetAwaiter().GetResult();
}
public static async Task Do()
{
for(int i=0;i<10;i++)
{
var task1 = Wait(5000);
var task2 = Wait(3000);
int[] result = await Task.WhenAll(task1, task2);
Console.WriteLine("waited for a total of " + result.Sum() + " ms");
}
}
public static async Task<int> Wait(int i)
{
await Task.Delay(i);
return i;
}
}
}

Application hangs while running async task

I am learning about async/await and created a dummy console application. When I try to get the result from async method the program just hangs. Any idea what is wrong in the following code.
static void Main(string[] args)
{
var task = Task.Factory.StartNew(() => 5);
var x = TestAsync();
//x.Start();
Console.WriteLine(x.Result);
}
private static Task<int> CalculateValue()
{
Console.WriteLine("In CalculateValue"); // This line is printed.
Task<int> t = new Task<int>(GetValue); // The program hangs here.
return t;
}
public static async Task<int> TestAsync()
{
int result = await CalculateValue();
return result;
}
private static int GetValue()
{
return 10;
}
First of all:
Task<int> t = new Task<int>(GetValue); // The program hangs here.
is incorrect, the program actually hangs here :
Console.WriteLine(x.Result);
.Result blocks current thread until task x completes execution and returns result. It never completes as it awaits task returned by CalculateValue method whis is this task:
Task<int> t = new Task<int>(GetValue);
This is so called 'cold Task' which means that it's a task in an inactive state.
To start a 'hot' task (which basically means start the task) use the Task.Run method:
Task<int> t = Task.Run(GetValue);

Async/Await - Vicious Circle C# 5.0

The code is below.
I want to call DoLongWork function asynchronously.
But the code ends up synchronous because DoLongWork doesn't await anything.
There is no need for awaiting something in DoLongWork function. Because function itself is long running. Not waiting any resource.
How can I get out of this vicious circle?
class Program
{
static void Main(string[] args)
{
Task<int> task = Foo("Something");
Console.WriteLine("Do it");
Console.WriteLine("Do that");
task.Wait();
Console.WriteLine("Ending All");
}
static async Task<int> Foo(string param)
{
Task<int> lwAsync = DoLongWork(param);
int res = await lwAsync;
return res;
}
static async Task<int> DoLongWork(string param)
{
Console.WriteLine("Long Running Work is starting");
Thread.Sleep(3000); // Simulating long work.
Console.WriteLine("Long Running Work is ending");
return 0;
}
}
You can use Task.Run to execute synchronous work on a background thread:
// naturally synchronous, so don't use "async"
static int DoLongWork(string param)
{
Console.WriteLine("Long Running Work is starting");
Thread.Sleep(3000); // Simulating long work.
Console.WriteLine("Long Running Work is ending");
return 0;
}
static async Task<int> FooAsync(string param)
{
Task<int> lwAsync = Task.Run(() => DoLongWork(param));
int res = await lwAsync;
return res;
}

How to get asynchronousy without new threads or async and await keywords but only Task

I wonder how to accomplish the same thing the below program does without using extra threads or await and async keywords but only Tasks. A sample code would be awesome. It seems to me that we need to use TaskCompletionSource and Async versions of the IO-bound operations or any long-running operations.
static void Main(string[] args)
{
Task t = Go();
Console.WriteLine("Hello World");
Task.Delay(1000).GetAwaiter().OnCompleted(() => { Console.WriteLine("Completed"); });
Console.ReadLine();
}
static async Task Go()
{
var task = PrintAnswerToLife();
await task;
Console.WriteLine("Done");
}
static async Task PrintAnswerToLife()
{
var task = GetAnswerToLife();
int answer = await task;
Console.WriteLine(answer);
}
static async Task<int> GetAnswerToLife()
{
var task = Task.Delay(2000);
await task;
int answer = 21 * 2;
return answer;
}
You can do a pretty straightforward translation of async / await into Task by using ContinueWith. Other translations are also possible, e.g., Task.Delay becomes System.Threading.Timer.
The basic pattern is, for any async method that does an await:
static async Task Go()
{
var task = PrintAnswerToLife();
await task;
Console.WriteLine("Done");
}
becomes:
static Task Go()
{
var tcs = new TaskCompletionSource<object>();
var task = PrintAnswerToLife();
task.ContinueWith(_ =>
{
Console.WriteLine("Done");
tcs.SetResult(null);
});
return tcs.Task;
}
Correct error handling is a lot more work.

Categories