Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
So I am trying to get my head wrapped around the async and await in C#, I have read a bunch, seen a few questions here on SO, but I am just not quite sure yet.
So I have written a little sample in hopes you can help me to understand a little clearer what is happening and when to use it. Hopefully my sample is correct.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var c = new MyClass();
c.AccessTheWeb("http://www.google.com");
Console.WriteLine("Waiting");
Console.Read();
}
}
public class MyClass
{
public async Task AccessTheWeb(string url)
{
var result = await GetUrl(url);
Console.Write(result);
}
public async Task<string> GetUrl(string url)
{
string result;
using (var client = new HttpClient())
{
result = await client.GetStringAsync(url);
}
return "Did async task";
}
}
}
I have an +async+ intro on my blog that you may find useful. It has several followup resources at the end that include tips such as:
Console Main usually use Wait on a top-level task.
Asynchronous methods should end with Async.
The program looks Ok to me, I tweaked a few things like waiting for the asynchronous operation to complete. Instead of waiting for user input, I used .Wait()
class Program
{
void Main(string[] args)
{
var c = new MyClass();
Console.WriteLine("Waiting ...");
c.AccessTheWeb("http://www.google.com").Wait();
}
}
public class MyClass
{
public async Task AccessTheWeb(string url)
{
var result = await GetUrl(url);
Console.Write(result);
}
public async Task<string> GetUrl(string url)
{
string result;
using (var client = new HttpClient())
{
result = await client.GetStringAsync(url);
}
return result; // why did you use "Did async task" ?
}
}
Normally when you call an async method the execution continues, with the method being executed in another thread, and you can do other things in the meantime.
You most likely want to check later if the method has completed. You can do so by checking the Task.IsCompleted or Task.TaskStatus properties.
But if for some reason you need to wait for the result of the function before you can move on, you use the await keyword before the method call, to ensure that the execution stops and waits for the method to complete before moving on. This also tells the compiler that it can take a break from executing this particular thread, because it is doing nothing but waiting.
There's a good MSDN article about all this.
Related
This question already has answers here:
Benefits of using async and await keywords
(5 answers)
Closed 1 year ago.
The below code example is reading from a file. It works - but can anyone explain what the advantage of the await? I mean, the code anyways would 'wait' for the file-reading to return a result, so what does it change to use the await? Can I add something to this example, to better illustrate the purpose of the await?
using System;
using System.IO;
using System.Threading.Tasks;
class Program
{
static void Main()
{
Task task = new Task(CallMethod);
task.Start();
task.Wait();
Console.ReadLine();
}
static async void CallMethod()
{
string filePath = "C:\\Temp\\sampleFile.txt";
Task<int> task = ReadFile(filePath);
Console.WriteLine("BEFORE");
int length = await task;
Console.WriteLine(" Total length: " + length);
}
static async Task<int> ReadFile(string file)
{
int length = 0;
Console.WriteLine("File reading is starting");
using (StreamReader reader = new StreamReader(file))
{
// Reads all characters from the current position to the end of the stream asynchronously
// and returns them as one string.
string s = await reader.ReadToEndAsync();
length = s.Length;
}
Console.WriteLine("File reading is completed");
return length;
}
}
Asynchronous code does not lock the current thread while waiting for an I/O request to complete (a request to the file system, or to the network, etc.).
The advantage is illustrated in what you are doing here:
Task<int> task = ReadFile(filePath);
Console.WriteLine("BEFORE");
int length = await task;
You're starting to read the file, but while you wait for a response from the file system, you can go do something else, like writing to the console.
Microsoft has a series of very well-written articles about Asynchronous programming with async and await. Read through those.
Some other comments about your code: You should avoid using async void. It doesn't allow you to know when the task finished (or if it finishes). So your task.Wait() doesn't actually do anything useful because of that.
Starting in C# 7.1, you can make the Main method async too, and use await CallMethod() instead of the 3 lines you have of creating the task.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Imagine the following function is defined in some other parts of the code or a 3rd party library:
public async Task<int> MyAsync()
Is it possible to transform that into a function that is exactly the same, but just lacks the async keyword? For example something like this:
public Task<int> MyAsync2()
{
...
var res = MyAsync();
...
}
Basically, I want this function:
public async Task Foo()
{
var i = await MyAsync();
...
}
and this function:
public async Task Foo2()
{
var i = await MyAsync2();
...
}
to have the same exact runtime behavior. If MyAsync executes the async code with the current context (e.g UI context), then MyAsync2 should too. The two should be interchangeable.
Is this possible?
public Task<int> MyAsync2()
{
return MyAsync();
}
However I do not understand why you ever need that: async modifier is an implementation detail and it does not change the API of the method. For instance, if MyAsync was implementing some interface, the interface would be
public interface MyInterface
{
Task<int> MyAsync();
}
It is possible doing your way, but what is the point of having MyAsync2() method returning task without marking it as async?
I also notice that inside MyAsync2() method, you call MyAsync() synchronously.
var res = MyAsync();
Please note that the type of res variable is a Task. To get the result from a task without blocking current thread is using await:
var res = await MyAsync();
But, if you you use await keyword inside body of a method, your MyAsync2() method should be marked with async keyword, unless you wait for the task to complete synchronously, which is NOT recommended:
var res = MyAsync();
var result = res.Result;
// or => var result = MyAsync().Result;
So, my answer is possible syntactically, but semantically there is no point for doing that, worse it can lead a subtle error, for example firing an asynchronous task running and forget.
I am working on a C# Hue application, I am creating the api calls myself for the learning experience. Since Hue consists of many network calls i wanted to also provide an async method for every sync method i create. I wrote some lines of code and thought to myself "This can't possibly be so easy", so now I'm here and wanted to ask if this is a good way to implement async functions? Also any other optimizations to my code are appreciated.
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace SharpHue
{
public class HueUtilities
{
const string DISCOVERY_URI = "http://www.meethue.com/api/nupnp";
public struct DiscoveryElement
{
[JsonProperty("id")]
public string ID;
[JsonProperty("internalipaddress")]
public string Address;
}
public static DiscoveryElement[] DiscoverBridges()
{
string data = "[]";
var request = WebRequest.CreateHttp(DISCOVERY_URI);
try
{
var response = request.GetResponse();
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
data = streamReader.ReadToEnd();
streamReader.Close();
response.Close();
}
return JsonConvert.DeserializeObject<DiscoveryElement[]>(data);
}
catch (Exception ex)
{
throw ex;
}
}
public static async Task<DiscoveryElement[]> DiscoverBridgesAsync()
{
return await Task.Run(() => DiscoverBridges());
}
}
}
Almost. But you should avoid Task.Run when there are true async alternatives. In your case that means replacing WebRequest class with HttpClient and call your code like this:
public static async Task<DiscoveryElement[]> DiscoverBridgesAsync()
{
using (var client = new HttpClient())
{
var result = await client.GetAsync(DISCOVERY_URI);
return await result.Content.ReadAsAsync<DiscoveryElement[]>();
}
}
As you can see there is no more use for the method that wrapped the synchronous call to an async call. It's now truly async/await compliant.
warning There might be some compile errors but should work.
More info: http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client
And please, read this: http://www.ben-morris.com/why-you-shouldnt-create-asynchronous-wrappers-with-task-run/
No async code is notoriously difficult to write that's why they added the async keyword. the problem tends to be that people don't understand what async code is and why use it. This code
var result = await Task.FromResult(0);
Is similar to writing
Task.FromResult(0).ContinueWith((task)=>
{
var result = task.Result;
});
If the code is not Asynchronous using async keyword wont make it so. Your code is Asynchronous because of what Task.Run dose, not the async Keyword. Stuff like ReadStream and ReadstreamAsync actually might do two completely different things like with file access.
Task.Run will not act the same in something like Asp.Net and Wpf since asp dose not have a UI thread. Also tasks have nothing to do with threads they can run on a single thread and do in some cases.Akavache is grate example of how to do async programing on a single thread. You have to be carful using async if you don't understand what will be done in the background.
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I have been looking everywhere to find good real world examples of the new Async and Await features in .net 4.5. I have come up with the following code to download a list of files and limit the number of concurrent downloads. I would appreciate any best practices or ways to improve/optimize this code.
We are calling the below code using the following statement.
await this.asyncDownloadManager.DownloadFiles(this.applicationShellViewModel.StartupAudioFiles, this.applicationShellViewModel.SecurityCookie, securityCookieDomain).ConfigureAwait(false);
We are then using events to add the downloaded files to an observablecollection (new thread safe version in .net 4.5) on the ViewModel.
public class AsyncDownloadManager
{
public event EventHandler<DownloadedEventArgs> FileDownloaded;
public async Task DownloadFiles(string[] fileIds, string securityCookieString, string securityCookieDomain)
{
List<Task> allTasks = new List<Task>();
//Limits Concurrent Downloads
SemaphoreSlim throttler = new SemaphoreSlim(initialCount: Properties.Settings.Default.maxConcurrentDownloads);
var urls = CreateUrls(fileIds);
foreach (var url in urls)
{
await throttler.WaitAsync();
allTasks.Add(Task.Run(async () =>
{
try
{
HttpClientHandler httpClientHandler = new HttpClientHandler();
if (!string.IsNullOrEmpty(securityCookieString))
{
Cookie securityCookie;
securityCookie = new Cookie(FormsAuthentication.FormsCookieName, securityCookieString);
securityCookie.Domain = securityCookieDomain;
httpClientHandler.CookieContainer.Add(securityCookie);
}
await DownloadFile(url, httpClientHandler).ConfigureAwait(false);
}
finally
{
throttler.Release();
}
}));
}
await Task.WhenAll(allTasks).ConfigureAwait(false);
}
async Task DownloadFile(string url, HttpClientHandler clientHandler)
{
HttpClient client = new HttpClient(clientHandler);
DownloadedFile downloadedFile = new DownloadedFile();
try
{
HttpResponseMessage responseMessage = await client.GetAsync(url).ConfigureAwait(false);
var byteArray = await responseMessage.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
if (responseMessage.Content.Headers.ContentDisposition != null)
{
downloadedFile.FileName = Path.Combine(Properties.Settings.Default.workingDirectory, responseMessage.Content.Headers.ContentDisposition.FileName);
}
else
{
return;
}
if (!Directory.Exists(Properties.Settings.Default.workingDirectory))
{
Directory.CreateDirectory(Properties.Settings.Default.workingDirectory);
}
using (FileStream filestream = new FileStream(downloadedFile.FileName, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
{
await filestream.WriteAsync(byteArray, 0, byteArray.Length);
}
}
catch(Exception ex)
{
return;
}
OnFileDownloaded(downloadedFile);
}
private void OnFileDownloaded(DownloadedFile downloadedFile)
{
if (this.FileDownloaded != null)
{
this.FileDownloaded(this, new DownloadedEventArgs(downloadedFile));
}
}
public class DownloadedEventArgs : EventArgs
{
public DownloadedEventArgs(DownloadedFile downloadedFile)
{
DownloadedFile = downloadedFile;
}
public DownloadedFile DownloadedFile { get; set; }
}
After suggestion by Svick - The following are direct questions:
What is the affect of embedding Async / Await in other Async / Await methods? (Write filestream to disk inside an Async / Await method.
Should a httpclient be used for each separate task or should they share a singe one?
Are events a good way to "send" the downloaded file reference to the viewmodel?
[I will also post in codereview]
If you embed async await you should use
Task.ConfigureAwait(false)
on anything that returns a Task otherwise the task will continue on the thread context of the caller which is unnecessary except on the UI thread. In summary, libaries should use ConfigureAwait(false) and UI code should not. That is about it!
I think your questions are not directly related to your code, so I will answer them here:
What is the effect of embedding Async / Await in other Async / Await methods? (Write filestream to disk inside an Async / Await method.)
async methods are meant to be combined like this. Actually that's the only thing async-await can be used to: combine asynchronous methods to create another asynchronous method.
What happens is that if you await a Task that is not finished yet, your method actually returns to the caller. Then, when the Task completes, your method is resumed on the original context (for example the UI thread in UI application).
If you don't want to continue on the original context (because you don't need it), you can change that by using ConfigureAwait(false), like you already do. There is no need to do this inside Task.Run(), because that code doesn't run in the original context.
Should a httpclient be used for each separate task or should they share a singe one?
The documentation of HttpClient says that its instance methods are not thread-safe, so you should use separate instance for each Task.
Are events a good way to "send" the downloaded file reference to the viewmodel?
I think events don't fit well together with async-await. In your case, it would work only if you used BindingOperations.EnableCollectionSynchronization and were also properly locking the collection in your own code.
I think a better alternative would be to use something like TPL Dataflow or Rx.
Using latest CTP5 with async/await keywords, I wrote some code, which apparently cannot compile:
class Program
{
public class MyClass
{
async public Task<int> Test()
{
var result = await TaskEx.Run(() =>
{
Thread.Sleep(3000);
return 3;
});
return result;
}
}
static void Main(string[] args)
{
var myClass = new MyClass();
//The 'await' operator can only be used in a method or lambda marked with the 'async' modifier error ??!!
int result = await myClass.Test();
Console.ReadLine();
}
}
What is th reason of "The 'await' operator can only be used in a method or lambda marked with the 'async' modifier error?" (I've selected the line which Visual Studio point me to)
I don't know if you can mark Main as async, but you need to include the async keyword in the declaration of any method that uses await. For example:
public async void DoStuffAsync ()
{
var myClass = new MyClass ();
int result = await myClass.TestAsync ();
}
await is not the same as Wait(); doing an await is a significant re-writing of that method, and in particular affects the expectation of how that method exits to the caller. You are right in that it doesn't actually do much (caveat: return types) except tell the compiler to enable some things (as do switches like unsafe, checked and unchecked if you think about it) - but consider: this actually matters hugely in your example. If Main() exits (and we assume no other threads) - you exe is toast. Gone. No longer exists. Adding async makes you consider that just because the method exits doesn't mean it has finished. You really don't want Main() exiting before you are ready.
As a secondary effect, this switch also formalises that the method can only return things like Task; without the switch, you might be tempted to make it async later, which could be a significantly breaking change.
An async method can have a return type of void or Task. If the return type is not void the caller can still use the standard Wait mechanism introduced in .Net 4 inside the Main entry method (which can not be marked async). Here's a simple example:
static void Main(string[] args)
{
string address = "http://api.worldbank.org/countries?format=json";
Task t = LoadJsonAsync(address);
// do other work while loading
t.Wait();
Console.WriteLine("Hit ENTER to exit...");
Console.ReadLine();
}
private async static Task LoadJsonAsync(string address)
{
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(address);
// Check that response was successful or throw exception
response.EnsureSuccessStatusCode();
// Read response asynchronously as JsonValue and write out top facts for each country
JsonArray readTask = await response.Content.ReadAsAsync<JsonArray>();
Console.WriteLine("First 50 countries listed by The World Bank...");
foreach (var country in readTask[1])
{
Console.WriteLine(" {0}, Capital: {1}",
country.Value["name"],
country.Value["capitalCity"]);
}
}