Start a new console app using the following code -
class Program
{
static void Main(string[] args)
{
while (true)
{
Task<string> readLineTask = Console.In.ReadLineAsync();
Debug.WriteLine("hi");
}
}
}
Console.In.ReadLineAsync is blocking and doesn't return until a line is entered in the console.. so "Hi" never gets written to the console.
Using await on Console.In.ReadLineAsync also blocks.
It was my understanding that the new Async CTP methods do not block.
What is the reason for this?
Here is another example
static void Main(string[] args)
{
Task delayTask = Task.Delay(50000);
Debug.WriteLine("hi");
}
This behaves as I expect, it goes straight to the next line and prints "hi" since Task.Delay does not block.
daryal provided the answer here
http://smellegantcode.wordpress.com/2012/08/28/a-boring-discovery/
It seems ReadLineAsync is not actually doing what it's supposed to do. Bug in the framework.
My solution is to use ThreadPool.QueueUserWorkItem in a loop so each call to ReadLineAsync is done on a new thread.
This can now be found in the documentation:
Read operations on the standard input stream execute synchronously. That is, they block until the specified read operation has completed. This is true even if an asynchronous method, such as ReadLineAsync, is called on the TextReader object returned by the In property.
Another solution:
static void Main()
{
using (var s = Console.OpenStandardInput())
using (var sr = new StreamReader(s))
{
Task readLineTask = sr.ReadLineAsync();
Debug.WriteLine("hi");
Console.WriteLine("hello");
readLineTask.Wait();// When not in Main method, you can use await.
// Waiting must happen in the curly brackets of the using directive.
}
Console.WriteLine("Bye Bye");
}
Related
I am trying to write a class with a method that will get some data from a REST API (the googleapi for youtube playlists) and dump that data into an ObservableCollection. The problem I am encountering is that when I call this:
this.getPlaylistItemsAsync().GetAwaiter().GetResult();
the code executes.
When I call this:
await this.getPlaylistItemsAsync();
it simply skips over the code.
I am pretty new to the whole asynchrounous programming thingy... I thikn I understand the basic concepts.. I just can't figure out how to do it :(
The full code is here:
#define DEBUG
//#define TestEnvi
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Newtonsoft.Json;
namespace IntuifaceYTPlaylist {
public class IFYT_Playlist {
public string playlistID {get;set;}= "PLYu7z3I8tdEmpjIoZHybXD4xmXXYrTqlk"; // The ID with which we identify our playlist
private string key = "supersecretAPIkey"; // The API-Key we use to access the google-API
public ObservableCollection<string> videosList {get;set;}= new ObservableCollection<string>();
public IFYT_Playlist () {
Console.WriteLine("Class Loaded!");
#if TestEnvi
this.getPlaylistItemsAsync().GetAwaiter().GetResult();
Console.WriteLine("This worked!");
await this.getPlaylistItemsAsync();
Console.WriteLine("This didn't!"); //In fact this line isn't even executed :(
#endif
}
#region getData
public async void update (){
this.getPlaylistItemsAsync().GetAwaiter().GetResult();
}
// Access the REST-API to retrieve the full dataset
// TODO: Manage connection to the API - DONE
// TODO: Parse JSON
public async Task<ObservableCollection<string>> getPlaylistItemsAsync(){
var output = new ObservableCollection<string>();
string URL = "https://www.googleapis.com/youtube/v3/playlistItems";
HttpClient client = new HttpClient();
string query = URL + "?key=" + this.key + "&part=contentDetails&playlistId=" + this.playlistID + "&maxResults=50";
var response = await client.GetStringAsync(query); //Dump the JSON string into an object!
# if DEBUG
// Dump the response into a file - just so we can check it if something goes wrong...
using (StreamWriter outputFile = new StreamWriter(Path.Combine("", "Dump.json")))
{
outputFile.WriteLine(response);
}
#endif
var responseData = JsonConvert.DeserializeObject<dynamic>(response);
// Iterate over the items in the list to get the VideoIDs of the individual videos
foreach (var item in responseData.items){
output.Add(JsonConvert.SerializeObject(item.contentDetails.videoId));
}
Console.WriteLine(output);
#if DEBUG //Let's see if that worked....
Console.WriteLine();
Console.WriteLine("Printing VideoIDs:");
Console.WriteLine();
foreach (var item in output){
Console.WriteLine(item);
}
Console.WriteLine();
#endif
this.videosList = output;
return output;
}
#endregion
}
}
The program I use to call this looks like this:
using System;
using IntuifaceYTPlaylist;
namespace TestEnvi
{
class Program
{
static void Main(string[] args)
{
Create();
}
static async void Create(){
IFYT_Playlist playlist = new IFYT_Playlist();
playlist.getPlaylistItemsAsync().GetAwaiter().GetResult();
Console.WriteLine("This worked!");
await playlist.getPlaylistItemsAsync();
Console.WriteLine("Did this?");
}
}
}
Invoked method immediately returns to the caller (i.e. to the Main) on first await and from there, both (the caller and the invoked method) run concurrently. Yet, since the Main finishes first, the whole program ends.
Thus, if you want to wait for asynchronous call completion you may change Create() to return Task rather than void and then you can wait such as: Create().Wait();
It's hard to tell from your code example, where exactly you're trying to update the list, because the code which you are pointing out to can't even be compiled. You can't use the await keyword in constructors, because constructors can't be async.
The main reason why you don't see console output is because your Main method doesn't wait for your async void Create to finish, because Create is async operation and as we know it's non blocking. Therefore your main thread just triggers the Create operation and continue doing other stuff below. But there is nothing below and that's it, the program is done.
To fix it, you should either turn your Main method to async method and call await Create(), or just call Create().Wait. You can also call Console.ReadLine if this is the console application.
By the way, it works with this.getPlaylistItemsAsync().GetAwaiter().GetResult();, because it's not asynchronous code any more, your Create method is blocked and it waits for the getPlaylistItemsAsync to finish. Similarly your Main method also waits for the Create to return, so that the program keep working.
You also have async void update method which you probably use somewhere (I don't know), so be careful with it since you don't have a way to know whether the method has finish its operation or not. Below is simplified explanation of asynchronous code in C# and why it might be bad to return void from the async method.
A bit about asynchronousy
The way how we can describe an asynchronous operations is that the operation is not blocking which means that you can tell that you want to begin the operation and continue doing other stuff not waiting the operation to finish its work. But this is not very useful to just start the operation (sometimes it might be useful), you usually want to do something when the operation is completed, failed etc. So in .NET the async operation returns Task or Task<T> which is the abstraction over the operation which might be completed or might be still in progress. Then you can attach your own code to be executed when a task is completed.
What happens under the hood when you await an operation
Keep in mind that this description is too simplified than what is actually happening.
So when you do something like this:
public async Task IFYT_Playlist () {
await this.getPlaylistItemsAsync();
... Do some other stuff when the `getPlaylistItemsAsync` has been completed
}
The IFYT_Playlist method attaches the code which is below await this.getPlaylistItemsAsync(); to the task which is returned by the method and return immediately. Again this is not what's actually happening, but can get you a basic idea:
public async Task IFYT_Playlist () {
Task resTask = this.getPlaylistItemsAsync();
return resTask.ContinueWith(t => ...Do some other stuff when the `getPlaylistItemsAsync` has been completed);
}
So that as it turned out async operation should return Task so that the caller will be able to attach a continuation to it (with ContinueWith) method. Do you see the problem now? If your return type is void, the caller won't be able to attach the code which should be executed when the operation has been completed. So, if getPlaylistItemsAsync's returns type is void, you can't await this.getPlaylistItemsAsync(), because it's impossible to call ContinueWith on nothing (void). Therefore you can't even have await with method that returns void.
public async Task IFYT_Playlist () {
await this.getPlaylistItemsAsync(); // doesn't compile
}
Therefore your update method should return Task or Task<T> for any suitable T in your case rather than nothing (void).
I am using .Net 4.7.2 and C# 7
In a class there are serveral methods, all void. Some of them can be executed asynchronously, others have to be executed sequentially. So I defined a list for the parallels
private void ExecuteSequential()
{
SomeMethod1();
SomeMethod2();
ExecuteParallelAsync();
SomeMethod3();
SomeMethod4();
}
private async void ExecuteParallelAsync()
{
List<Action> methods = new List<Action>()
{
MyMethod1,
MyMethod2,
MyMethod3
};
await Task.Run( () => { Parallel.ForEach( methods , ( currentMethod ) => currentMethod.Invoke() ); } );
}
Before SomeMethod3 happens to be executed ExecuteParallelAsync should be finished entirely.
Because that's not the case, apparently something is wrong with my usage of async and await.
What I am doing wrong?
Thanks in advance!
async void - all bets are off; in reality, you should never write an async void method unless you're in the tiny tiny set of extreme corner cases that require it, such as async event-handlers.
Before SomeMethod3 happens to be executed ExecuteParallelAsync should be finished entirely.
how could it possibly know? it is: async void, which means it doesn't give anything to the caller that indicates the state.
To do that, it must be:
private async Task ExecuteParallelAsync() // or ValueTask
and you must await it at the call site
await ExecuteParallelAsync();
Marc's answer is the correct solution, but I wanted to explain more about why.
A very key thing to understand about async methods is that:
They start synchronously.
When the await keyword is used, and await given an incomplete Task, the method returns - yes, even if you're only halfway through your method. The magic is in what it returns.
So lets look at what your code does:
Call ExecuteParallelAsync().
ExecuteParallelAsync() starts running synchronously.
Task.Run returns a Task object that is not complete yet.
The await keyword inspects the Task, sees that it is not complete, so it creates a new Task, signs up the rest of the method as a continuation of that Task (there is nothing left to do in this case, but it still happens) and returns.
Because the return type is void it cannot return a Task. But it still returns!
So all that means that ExecuteParallelAsync() returns before the Task.Run is completed, and ExecuteSequential() has no way to tell when the work is actually complete.
This is commonly called "fire and forget" (i.e. "go do this and I don't care when or if you finish").
As Marc's answer points out, if you want to know when it's done, you need to return a Task, which you can then await to know when it's done.
Microsoft has very well written articles about asynchronous programming that you may benefit from reading: Asynchronous programming with async and await
If you want an implementation without async/await sugar keyword:
private void ExecuteParallelAsync()
{
List<Action> methods = new List<Action>()
{
MyMethod1,
MyMethod2,
MyMethod3
};
Task.WaitAll(methods.Select((action) => Task.Run(action)).ToArray())
}
Step 1, reproduce
public void Method()
{
SomeMethod();
SomeMethod();
ExecuteParallelAsync(); //< ---fire and forget
SomeMethod();
SomeMethod();
Console.ReadLine();
}
private void SomeMethod() => Console.WriteLine($"SomeMethod");
private async void ExecuteParallelAsync()
{
Console.WriteLine($"START");
await Task.Delay(TimeSpan.FromMilliseconds(100));
Console.WriteLine($"END");
}
Output
SomeMethod
SomeMethod
START
SomeMethod
SomeMethod
END
Step 2, trying to fix
"Oh yes, I forgot to await my function"
await ExecuteParallelAsync(); //Change 1. "I forgot to await"
Output
Compilation error (line 12, col 3): The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
Compilation error (line 12, col 3): Cannot await 'void'
Step 3, fix
Addressing both errors from step 2.
// Change 2
// was:public void Main()
// which caused: "The 'await' operator can only (...)"
public async Task Main()
(...)
// Change 3
// was: private async void ExecuteParallelAsync()
// which caused "Compilation error (line 12, col 3): Cannot await 'void'"
private async Task ExecuteParallelAsync()
Run.
Output:
SomeMethod
SomeMethod
START
END
SomeMethod
SomeMethod
For reference, we could have waited for ExecuteParallelAsync without the await keyword, but await is the correct way in all scenarios except the tiny minority where it's not.
a small complete example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace test
{
class Program
{
static void Main(string[] args)
{
SomeMethod1();
ExecuteParallelAsync();
SomeMethod2();
Console.ReadKey();
}
static void SomeMethod1()
{
Console.WriteLine("SomeMethod1");
}
static void SomeMethod2()
{
Console.WriteLine("SomeMethod2");
}
static void ExecuteParallelAsync()
{
Console.WriteLine("\tstart of ExecuteParallelAsync");
var rd = new Random();
List<Action> methods = new List<Action>()
{
()=>{Thread.Sleep((int) Math.Ceiling(rd.NextDouble()*1000));Console.WriteLine("MyMethod1"); },
()=>{Thread.Sleep((int) Math.Ceiling(rd.NextDouble()*1000));Console.WriteLine("MyMethod2"); },
()=>{Thread.Sleep((int) Math.Ceiling(rd.NextDouble()*1000));Console.WriteLine("MyMethod3"); },
};
Task.WaitAll(methods.Select((action) => Task.Run(action)).ToArray());
Console.WriteLine("\tend of ExecuteParallelAsync");
}
}
}
example of a result:
SomeMethod1
start of ExecuteParallelAsync
MyMethod2
MyMethod3
MyMethod1
end of ExecuteParallelAsync
SomeMethod2
I'm trying to find out how to use WhenAll to let two methods run at once, and once they both finish, collect the results without blocking by using .Result
I have this little console app test:
using System.Diagnostics;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
public static void Main(string[] args)
{
var run = TaskRunner();
Debug.WriteLine(run);
if (run.IsCompleted)
{
Debug.WriteLine("this worked!");
} else
{
Debug.WriteLine("this failed!");
}
}
public static async Task<string> TaskRunner()
{
var taskOne = OneAsync();
var taskTwo = TwoAsync();
var tasks = await Task.WhenAll(taskOne, taskTwo);
var retval = tasks[0] + tasks[1];
return retval;
}
public static Task<string> OneAsync()
{
return Task.Run(() =>
{
return "test1";
});
}
public static Task<string> TwoAsync()
{
return Task.Run(() =>
{
return "test2";
});
}
}
}
This currently prints this worked! to my Output window... However, if I comment out Debug.WriteLine(run); it prints this failed!... Why does the Task complete simply by being logged to the output window?
I'm trying to understand a huge problem in a complex piece of code and this little test is my MCVE to hopefully shed some light on what is happening behind the scenes.
This happens just by pure chance. The way you are starting your task is with Task.Run. This essentially creates a new thread on which the (synchronous) action is executed. It returns a task for the completion of that thread.
So OneAsync and TwoAsync will each spawn a new thread that then immediately returns a string. This will happen very quickly but there’s still some overhead for creating those threads which means that it won’t be instantaneous.
TaskRunner then calls both those methods (spawning the threads), and then asynchronously waits for both threads to finish. Since the threads are not completely instantly, this TaskRunner method also won’t complete instantly.
Now, in your main, you are starting the asynchronous TaskRunner, which we figured will take “a very short moment”. You do not await the task, so the execution continues immediately. Debug.WriteLine is executed to print something (it probably doesn’t really matter that it’s the task in question that is being printed), and then you are checking the state of the task.
Since printing stuff is relatively slow (compared to other operations), this is probably the reason why the tasks ends up being completed. And when you remove the printing, the if is just reached too quickly for the task to finish.
As you likely noticed, working like that with asynchronous tasks does not appear to be a good idea. That’s why you should always await the task when you depend on its result.
// note the *async* here; async main methods are supported with C# 7.1
public static async void Main(string[] args)
{
var run = TaskRunner();
// await the task
await run;
if (run.IsCompleted)
{
Debug.WriteLine("this worked!");
}
else
{
Debug.WriteLine("this failed!");
}
}
I found this piece of code online on csharpstar.com as I was trying to understand more about async and await. Can someone help me understand why when I debug it I reach the line where await client.GetStringAsync ("http://www.CsharpStar.com"); is assigned to result, and then the debugger doesn't move onto the next line from try, and doesn't enter catch either, it just seems to resume execution from Main?
If the await line throws a timeout error or something should it not go to catch?
Also weird that when control/flow resumes to Main, it doesn't go through line ReadLine(), which it executed earlier (before entering the GetSite method), however the ReadLine() takes effect after exiting the GetSite method.
What is the explanation of await function disrupting the regular flow? Why can't I debug the next line, so I can see the value stored into the result variable?
using System;
using System.Net.Http;
using System.Threading.Tasks;
using static System.Console;
namespace CSharpStar
{
class Program
{
static void Main(string[] args)
{
Task.Factory.StartNew(() => GetSite());
ReadLine(); // **...to here (2)**
}
private async static Task GetSite()
{
HttpClient client = new HttpClient();
try
{
var result = await client.GetStringAsync ("http://www.CsharpStar.com"); // **debugger jumps from here (1)**
WriteLine(result);
}
catch (Exception exception)
{
try
{
//This asynchronous request will be invoked if the first request is failed.
var result = await client.GetStringAsync ("http://www.easywcf.com");
WriteLine(result);
}
catch
{
WriteLine("Entered Catch Block");
}
finally
{
WriteLine("Entered Finally Block");
}
}
}
}
}
Not sure what article you were reading, but you should stop there. Task.Factory.StartNew is not recommended, but Task.Run is.
What is happening is that the control is returned to the caller (Main in this case) as soon as the await keyword is reached. Since you are not awaiting for the Task to finish, the program goes on to the Console.WriteLine line. This is known as a fire and forget call.
If you want to wait for the function to finish, change your code to:
static void Main(string[] args)
{
// change to the recommended Task.Run method
var task = Task.Run(() => GetSite());
task.GetAwaiter().GetResult(); // block until the Task is finished
ReadLine();
}
I am playing with the new Async CTP bits, and I can't get it work with either server-side or just command-line program (and all the examples are either WPF or Silverlight). For example, some trivial code like:
class Program {
static void Main() {
Program p = new Program();
var s = p.Ten2SevenAsync();
Console.WriteLine(s);
}
private async Task<int> Ten2SevenAsync() {
await TaskEx.Delay(10000);
return 7;
}
}
returns immediately and prints System.Threading.Tasks.Task1[System.Int32]` instead of waiting for 10 secs and return 7 (as I would expect). Must be something obvious that I am missing.
The whole point of the await-based code is that it is indeed "execute the next stuff when this is finished" (a callback), and not "block the current thread until this has finished".
As such, from Ten2SevenAsync you get back a task, but that task is not yet complete. Writing the task to the console does not mean it waits for it to complete. If you want to block on the task's completion:
static void Main() {
Program p = new Program();
var s = p.Ten2SevenAsync();
Console.WriteLine(s.Result);
}
or more explicitly:
static void Main() {
Program p = new Program();
var s = p.Ten2SevenAsync();
s.Wait();
Console.WriteLine(s.Result);
}
I believe you just need to change the 4th line of your example to:
var s = await p.Ten2SevenAsync();
s is a reference to an asynchronous task. I haven't played with this myself yet so I'm not sure of the syntax, but there will be members of s that will allow you to check whether or not the task has completed, and then retrieve the result.