I have been reasearching once again the async tasks. No mater how i set the Tasks, my application suffers from UI freeze all the time. I have the following code for downloading the string from a webpage:
internal string DownloadString(string URL)
{
var result = LoadCompanyContracts(URL);
return result.Result;
}
internal async Task<string> LoadCompanyContracts(string URL)
{
Task<string> task2 = Task<string>.Factory.StartNew(() =>
{
for (int i = 0; i <= 10000000; i++) Console.WriteLine(i);
WebClient wc = new WebClient();
string tmp = wc.DownloadString(new Uri(URL));
return tmp;
});
return task2.Result;
}
When i execute this task and during the for loop the UI of my application is freezing. Even though i believe that this code should not freeze the UI i am not able to find a solution. I have tried many different options and really want to use tasks instead of threads or events with webclient async.
Info: I am using .net 4.5 for my project. The difference in my code is that these functions are inside a class library(don't know if it matters).
Is it possible to run this code without blocking the user interface with async await by calling the DownloadString function from my code? If not what are the alternatives(any good nuget packages)?
The async keyword doesn't make something run asynchronously, it enables you to use await to await an already asynchronous operation. You need to use
DownloadStringTaskAsync to truly download in an asynchronous manner:
internal async Task<string> LoadCompanyContracts(string URL)
{
....
using(var wc = new WebClient())
{
string tmp = await wc.DownloadStringTaskAsync(new Uri(URL));
return tmp;
}
}
await by itself returns execution in the original execution context (ie the UI thread). This may or may not be desirable, which is why library code typically uses ConfigureAwait(false); and lets the final user of the library to decide how to await:
string tmp = await wc.DownloadStringTaskAsync(new Uri(URL))
.ConfigureAwait(false);
Finally, there's no point in awaiting if you are going to call .Result from the top-level function. There is no point in using await at all if you don't want to do use the method's result in your code. LoadCompanyContracts could be just:
internal Task<string> LoadCompanyContracts(string URL)
{
....
using(var wc = new WebClient())
{
return wc.DownloadStringTaskAsync(new Uri(URL))
.ConfigureAwait(false);
}
}
Oops
Typically, you don't need to use await at all if you just return the result of an asynchronous operation. The method could just return wc.DownloadStringTaskAsync(..); BUT that would cause the method to return and dispose the WebClient before download finishes. Avoiding the using block isn't a solution either, as it will let an expensive object like WebClient alive longer than necessary.
That's why HttpClient is preferable to WebClient: a single instance supports multiple concurrent calls, which means you can have just one instance eg as a field and reuse it, eg:
HttpClient _myClient =new HttpClient();
internal Task<string> LoadCompanyContractsAsync(string URL)
{
....
return _myClient.GetStringAsync(new Uri(URL))
.ConfigureAwait(false);
}
}
You could get rid of your DownloadString since it doesn't do anything on top of LoadCompanyContracts. If it does use the result of LoadCompanyContracts, it should be rewritten as:
internal async Task<string> DownloadString(string URL)
{
var result = await LoadCompanyContracts(URL);
//Do something with the result
return result;
}
EDIT
The original answer used DownloadStringAsync which is a legacy method that raises an event when download completes. The correct method is DownloadStringTaskAsync
EDIT 2
Since we are talking about a UI, the code can be made asynchronous all the way to the top event handler by using the async void syntax for the handler, eg async void Button1_Click, eg:
async void LoadCustomers_Click(...)
{
var contracts=await LoaCompanyContracts(_companyUrls);
txtContracts>Text=contracts;
}
In this case we want to return to the original thread, so we don't use ConfigureAwait(false);
Related
I started to look into Task, async/await concepts is c# and I'm having big problems understanding it, well at least i don't know how to implement it. I started rewriting an older test program i had written before, but now instead of threading i want to use these new concepts. Basically the layout is as it follows:
I have a simple class where i download the HTML content of a web page.
I process that in another class where i basically just parse the page to my model. Later on i want to display that to my UI.
The problem is that my program is not responsive, it blocks the UI while I'm processing the info.
I started learning this 2 days ago, i have read a lot of stuff online, including MSDN and some blogs but yet I'm unable to figure it out. Maybe someone can provide a look as well
HtmlDOwnloadCOde:
public async Task<string> GetMangaDescriptionPage(string detailUrl)
{
WebClient client = new WebClient();
Stream data = await client.OpenReadTaskAsync(detailUrl);
StreamReader reader = new StreamReader(data);
string s = reader.ReadToEnd();
data.Dispose();
reader.Dispose();
data.Close();
reader.Close();
return s;
}
My parse class code:
public async Task<MangaDetailsModel> ParseMangaDescriptionPage()
{
ParseOneManga pom = new ParseOneManga();
string t1 = await pom.GetMangaDescriptionPage(selectedManga.url);
HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(t1);
var divs = htmlDoc.DocumentNode.Descendants("div").Where(x => x.Attributes.Contains("id") &&
x.Attributes["id"].Value.Contains("title")).ToArray();
mangaDetails.mangaName = divs[0].Element("h1").InnerText;
mangaDetails.description = divs[0].Descendants("p").Single().InnerText ?? "DSA";
var tds = divs[0].Descendants("td");
int info = 0;
var chapters = htmlDoc.DocumentNode.Descendants("div").Where(x => x.Attributes.Contains("id") &&
x.Attributes["id"].Value.Contains("chapters")).ToArray();
var chapterUi = chapters[0].Descendants("ul").Where(x => x.Attributes.Contains("class") &&
x.Attributes["class"].Value.Contains("chlist"));
foreach (var li in chapterUi)
{
var liChapter = li.Descendants("li");
foreach (var h3tag in liChapter)
{
var chapterH3 = h3tag.Descendants("a").ToArray();
SingleManagFox chapterData = new SingleManagFox();
chapterData.name = chapterH3[1].InnerHtml;
chapterData.url = chapterH3[1].GetAttributeValue("href", "0");
mangaDetails.chapters.Add(chapterData);
}
};
return mangaDetails;
}
UI code:
private async void mainBtn_Click(object sender, RoutedEventArgs e)
{
if (mangaList.SelectedItem != null)
{
test12((SingleManagFox)mangaList.SelectedItem);
}
}
private async void test12(SingleManagFox selectedManga)
{
selectedManga = (SingleManagFox)mangaList.SelectedItem;
MangaDetails mangaDetails = new MangaDetails(selectedManga);
MangaDetailsModel mdm = await mangaDetails.ParseMangaDescriptionPage();
txtMangaArtist.Text = mdm.artisName;
txtMangaAuthor.Text = mdm.authorName;
chapterList.ItemsSource = mdm.chapters;
}
Sorry if its trivial but i cannot figure it out myself.
When going async you need to try to go async all the way and avoid mixing blocking calls with async calls.
You are using async void in the event handler with no await.
Try to avoid async void unless it is an event handler. test12 should be updated to return Task and awaited in the event handler mainBtn_Click.
private async void mainBtn_Click(object sender, RoutedEventArgs e) {
if (mangaList.SelectedItem != null) {
await test12((SingleManagFox)mangaList.SelectedItem);
}
}
private async Task test12(SingleManagFox selectedManga) {
selectedManga = (SingleManagFox)mangaList.SelectedItem;
MangaDetails mangaDetails = new MangaDetails(selectedManga);
MangaDetailsModel mdm = await mangaDetails.ParseMangaDescriptionPage();
txtMangaArtist.Text = mdm.artisName;
txtMangaAuthor.Text = mdm.authorName;
chapterList.ItemsSource = mdm.chapters;
}
Also consider updating the web call to use HttpClient if available.
class ParseOneManga {
public async Task<string> GetMangaDescriptionPageAsync(string detailUrl) {
using (var client = new HttpClient()) {
string s = await client.GetStringAsync(detailUrl);
return s;
}
}
}
Reference: - Async/Await - Best Practices in Asynchronous Programming
Quite often people think that async-await means that multiple threads are processing your code at the same time. This is not the case, unless you explicitly start a different thread.
A good metaphore that helped me a lot explaining async-await is the restauran metaphor used in this interview with Eric Lippert. Search somewhere in the middle for async-await.
Eric Lipperts compares async-await processing with a cook who has to wait for his water to boil. Instead of waiting, he looks around if he can do other things instead. When finished doing the other thing, he comes back to see if the water is boiling and starts processing the boiling water.
The same is with your process. There is only one thread busy (at a time). This thread keeps processing until he has to await for something. This something is usually a fairly long process that is processed without using your CPU core, like writing a file to disk, loading a web page, or querying information from an external database.
Your thread can only do one thing at a time. So while it is busy calculating something, if can't react on operator input and your UI freezes, until the calculations are done. Async await will only help if there are a lot of times your thread would be waiting for other processes to complete
If you call an async function, you are certain that somewhere in that function is an await. In fact, if you declare your function async, and your forget to await in it, your compiler will warn you.
When your call meets the await in the function, your thread goes up its call stack to see if it can do other things. If you are not awaiting, you can continue processing, until you have to await. The thread goes up its call stack again to see if one of the callers is not awaiting etc.
async Task ReadDataAsync()
{
// do some preparations
using (TextReader textReader = ...)
{
var myReadTask = textReader.ReadToEndAsync();
// while the textReader is waiting for the information to be available
// you can do other things
ProcessSomething();
// after a while you really need the results from the read data,
// so you await for it.
string text = await MyReadTask;
// after the await, the results from ReatToEnd are available
Process(text);
...
There are some rules to follow:
an async function should return Task instead of void and Task<TResult> instead of TResult
There is one exception: the async event handler returns void instead of Task.
Inside your async function you should await somehow. If you don't await, it is useless to declare your function async
The result of await Task is void, and the result of await Task<TResult> is TResult
If you call an async function, see if you can do some processing instead of waiting for the results of the call
Note that even if you call several async functions before awaiting for them, does not mean that several threads are running these functions synchronously. The statement after your first call to the async function is processed after the called function starts awaiting.
async Task DoSomethingAsync()
{
var task1 = ReadAsync(...);
// no await, so next statement processes as soon as ReadAsync starts awaiting
DoSomeThingElse();
var task2 = QueryAsync(...);
// again no await
// now I need results from bothtask1, or from task2:
await Task.WhenAll(new Task[] {task1, task2});
var result1 = Task1.Result;
var result2 = Task2.Result;
Process(result1, result2);
...
Usually all your async functionality is performed by the same context. In practice this means that you can program as if your program is single threaded. This makes the look of your program much easier.
Another article that helped me a lot understanding async-await is Async-Await best practices written by the ever so helpful Stephen Cleary
I have 2 methods: the first sends HTTP GET request on one address and the second calls it multiple times (so, it sends request to many IPs). Both methods are async, so they don't block code execution while the requests are proccessing remotely. The problem is, due to my poor C# knowledge, I don't know how to send all the requests simultaneously, not one after another (which my code does). That's my code:
public static async Task<string> SendRequest(Uri uri)
{
using (var client = new HttpClient())
{
var resp = await client.GetStringAsync(uri).ConfigureAwait(false);
return resp;
}
}
public static async Task<string[]> SendToAllIps(string req)
{
string[] resp = new string[_allIps.Length];
for (int i = 0; i < _allIps.Length; i++)
{
resp[i] = await SendRequest(new Uri(_allIps[i] + req));
}
return resp;
}
How to make SendToAllIps send requests without awaiting for previous task result? Also SendToAllIps must return an array of responses when all the requests are finished. As far as I understand, this can be done with Task.WaitAll, but how to use it in this particular situation?
You can use Task.WhenAll to await a collection of tasks:
public static async Task<string[]> SendToAllIps(string req)
{
var tasks = _allIps.Select(ip => SendRequest(new Uri(ip + req)));
return await Task.WhenAll(tasks);
}
Answers provided above provide the correct way of doing it but doesn't provide rationale, let me explain what's wrong with your code:
Following line creates an issue:
resp[i] = await SendRequest(new Uri(_allIps[i] + req));
Why ?
As you are awaiting each individual request, it will stop the processing of the remaining requests, that's the behavior of the async-await and it will be almost the synchronous processing of each SendRequest when you wanted then to be concurrent.
Resolution:
SendRequest being an async method returns as Task<string>, you need add that to an IEnumerable<Task<string>> and then you have option:
Task.WaitAll or Task.WhenAll
Yours is Web API (Rest Application), which needs a Synchronization Context, so you need Task.WhenAll, which provides a Task as result to wait upon and integrate all the task results in an array, if you try using Task.WaitAll it will lead to deadlock, as it is not able to search the Synchronization Context, check the following:
WaitAll vs WhenAll
You can use the Task.WaitAll only for the Console application not the Web Application, Console App doesn't need any Synchronization Context or UI Thread
public static async Task<string[]> SendToAllIps(string req)
{
var tasks = new List<Task<string>>();
for (int i = 0; i < _allIps.Length; i++)
{
// Start task and assign the task itself to a collection.
var task = SendRequest(new Uri(_allIps[i] + req));
tasks.Add(task);
}
// await all the tasks.
string[] resp = await Task.WhenAll(tasks);
return resp;
}
The key here is to collect all the tasks in a collection and then await them all using await Task.WhenAll. Even though I think the solution from Lee is more elegant...
I'm learning how to use Tasks in MVC and I get completly lost. I need to download the source from selected webpage, find one element, get its value and return it. That's it.
For this I am using HtmlAgilityPack and HttpClient to fetch the webpage.
The problem that occurs is where nothing is waiting for response from httpClient and thus results that response generation completed when Task was still in progress. (An asynchronous module or handler completed while an asynchronous operation was still pending.)
I read lots of threads in here ,codeproj and some blogs, still don't understand what's the problem. Most common explanation is about resulting type of void in async method, but I cannot find any other way to return awaiting value, than this:
public float ReadPrice(Uri url)
{
switch (url.Host)
{
case "www.host1.xy":
return ParseXYZAsync(url).Result;
default:
return float.Parse("99999,99");
}
}
private Task<float> ParseXYZAsync(Uri url)
{
loadPage(url);
var priceNode = document.DocumentNode.SelectSingleNode(
#"//*[#id='pageWrapper']/div[4]/section[1]/div[4]/div[1]/div[1]/span");
var price = priceNode.InnerText;
...
return priceInFloat;
}
private async Task LoadPage(Uri url)
{
HttpClient http = new HttpClient();
var response = await http.GetByteArrayAsync(url);
String source = Encoding.GetEncoding("utf-8")
.GetString(response, 0, response.Length - 1);
source = WebUtility.HtmlDecode(source);
document.LoadHtml(source);
}
In order to figure out what's wrong you need to understand one key concept with async-await. When an async method hits the first await keyword, control is yielded back to the calling method. This means that when you do this:
loadPage(url);
The method will synchronously run until it hits:
var response = await http.GetByteArrayAsync(url);
Which will yields control back to ParseWebSite, which will continue execution and will probably end before the async operation has actually completed.
What you need to do is make LoadPage return a Task and await for it's completion:
private async Task<float> ParseWebsiteAsync(Uri url)
{
await LoadPageAsync(url);
var priceNode = document.DocumentNode.SelectSingleNode
(#"//*[#id='pageWrapper']/div[4]/section[1]/div[4]/div[1]/div[1]/span");
var price = priceNode.InnerText;
return priceInFloat;
}
private async Task LoadPageAsync(Uri url)
{
HttpClient http = new HttpClient();
var source = await http.GetAsStringAsync(url);
source = WebUtility.HtmlDecode(source);
document.LoadHtml(source);
}
Side Notes:
Do follow .NET naming conventions. Methods should be PascalCase and not camelCase
Do add the "Async" postfix for asynchronous methods. E.g, LoadPage should become LoadPageAsync.
private async void loadPage(Uri url) needs to return a Task:
private async Task loadPage(Uri url)
then you need to await it in the calling method:
private async Task<float> parseWEBSITEXY(Uri url)
{
await loadPage(url);
...
}
In you code load page starts and it returns immediately.
One more thing - it is not recommended to use async void, except for event handlers. Always return Task.
I have a webservice that loads up some plugins (dlls) and calls their Process method. One of the plugins takes a list of members and ensures that they are all included in a MailChimp list.
Here is the code that adds the users to the MailChimp group.
private async Task AddMCUsers(List<Member> _memberList)
{
using (var http = new HttpClient())
{
var creds = Convert.ToBase64String(Encoding.ASCII.GetBytes("user:password");
http.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", creds);
string memberURI = string.Format(#"{0}lists/{1}/members", _baseURI, _memberGroupId);
var jss = new JavaScriptSerializer();
foreach (var user in _memberlist)
{
var _addStatus = "";
try
{
var content = jss.Serialize(new MCPost()
{
email_address = user.Email,
status = "subscribed",
merge_fields = new MCMergeFields()
{
FNAME = user.Firstname,
LNAME = user.Lastname
}
});
using(var result = await http.PostAsync(memberURI, new StringContent(content,Encoding.UTF8, "application/json")))
{
var resultText = await result.Content.ReadAsStringAsync();
if(result.IsSuccessStatusCode)
{
_addStatus = "Success";
var _returnedUser = jss.Deserialize<MCMember>(resultText);
//Store new user's id
user.ServiceId = _returnedUser.id;
}
else
{
_addStatus = "Fail";
}
}
}
catch {
_addStatus = "Error";
}
LogEvent("Add User - " + _addStatus, string.Format("Id: {0} - {1} {2} (Account: {3}) : {4}", user.Id, user.Firstname, user.Lastname, user.AccountId, user.Email));
}
}
}
In normal procedural code, this wouldn't be a problem. However, the only Post method available on the httpClient was PostAsync. Being fairly new to the async/await stuff, I'm not sure the ramifications on the rest of my code ... particularly as it relates to my attempt to reuse the httpClient instead of instantiating a new one for each http call.
I'm not sure what happens with await when its wrapped in a foreach like I have. Will I run into issues with reusing the httpClient to make repeated calls when running asynchronously?
My other question is, what is actually going to be returned. IOW, my understanding is that await returns a Task. However, here, I'm looping through the list and making multiple calls to await PostAsync. My method returns a Task. But which task gets returned? If my calling method needs to wait for completion before moving on, what does its call look like?
private void Process()
{
//Get List
var task = AddMCUsers(list);
task.Wait();
//Subsequent processing
}
I've read that you should use Async all the way. Does this mean my calling method should look more like this?
public async Task Process()
{
//Get list
...
await AddMCUsers(list);
//Other processing
}
Thanks to whatever help you can offer on this.
In normal procedural code, this wouldn't be a problem.
The whole point of async/await is to write asynchronous code in a way that looks practically identical to "normal" synchronous code.
Being fairly new to the async/await stuff, I'm not sure the ramifications on the rest of my code ... particularly as it relates to my attempt to reuse the httpClient instead of instantiating a new one for each http call.
HttpClient was intended to be reused; in fact, it can be used for any number of calls simultaneously.
I'm not sure what happens with await when its wrapped in a foreach like I have.
One way to think of it is that await "pauses" the method until its operation completes. When the operation completes, then the method continues executing. I have an async intro that goes into more detail.
Will I run into issues with reusing the httpClient to make repeated calls when running asynchronously?
No, that's fine.
IOW, my understanding is that await returns a Task.
await takes a Task. It "unwraps" that task and returns the result of the task (if any). If the task completed with an exception, then await raises that exception.
My method returns a Task. But which task gets returned?
The Task returned from an async method is created by the async state machine. You don't have to worry about it. See my intro for more details.
If my calling method needs to wait for completion before moving on, what does its call look like? ... I've read that you should use Async all the way. Does this mean my calling method should look more like this?
Yes, it should look like your second snippet:
public async Task ProcessAsync()
{
//Get list
...
await AddMCUsers(list);
//Other processing
}
The only thing I changed was the Async suffix, which is recommended by the Task-based Asynchronous Pattern.
in your code you should be fine with reusing the HttpClient. What async / await is allow the code to release the execution thread to prevent locking a cpu thread while waiting for the web response. It also releases control back to the caller. When releasing code back to the caller it means that if your Process function does not await your AddMCUsers, Process could finish before AddMCUsers (useful in fire and forget situations to not await a method).
What async/await do not do is affect the logical flow of an individual method. When you await an async web call the execution is paused and then resumed at the same point once the web call returns. There is also thread context tracking and the code resumes in the same context (ie. UI thread or background thread depending on the parent) by default, but this can be changed if needed.
At some point in your code you may want to have a method that blocks until your async code competes and that is where you will want your Task.Wait() call to block execution. If all you use is awaits then it is possible for your program to end before your task competes. See the code example below.
class Program
{
static void Main(string[] args)
{
Task waitForMe = Task.Run(() => waitAsync());
}
static async Task waitAsync()
{
await Task.Delay(5000);
}
}
in the sample with out a Task.Wait call to block the Main method the program will end before the 5 second wait is complete. Having a main method of the following will cause the program to wait for 5 seconds before exiting:
static void Main(string[] args)
{
Task waitForMe = Task.Run(() => waitAsync());
waitForMe.Wait();
}
I have a method which does a long action using an async task
Now, I want to add a cache mechanism that will be transparent in the same method.
Now, I could always fetch my cache result and wrap it with a Task so it will "work" but I want to prevent the context switch that I will get.
Here's an example of what I have:
var result = await LongTask();
private async Task<string> LongTask()
{
return await DoSomethingLong();
}
And here's an example of what I want:
var result = await LongTask();
private async Task<string> LongTask()
{
if(isInCache)
{
return cachedValue(); // cache value is a const string you can do return "1" instead.
}
// else do the long thing and return my Task<string>
return await DoSomethingLong();
}
Now I'm surprised to see that this compiled and worked
Something tells me that I'm not doing it correctly.
Here's another similar example that I've tested:
private async Task<string> DownloadString(bool sync)
{
using (WebClient wc = new WebClient())
{
var task = wc.DownloadStringTaskAsync("http://www.nba.com");
if(sync)
return task.Result;
return await task;
}
}
And here's the code:
var res = DownloadString(true);
string str1 = await res;
var res2 = DownloadString(false);
string str2 = await res2;
From what I've read here task.Result executes the task synchronously and returns a string.
Now I see the request via Fiddler and my program get's stuck on the return task.Result line even though I see a 200 OK and I wait a long time.
Bottom Line:
Whats the best\correct way to use caching inside an async method(e.g. doing something synchronously in some cases without create a context switch overhead?
Why does my second block of code with the DownloadString get stuck?
First of all, if after a call to an async method the returned task is already completed there would be no context switch, because none is needed. So this is completely acceptable:
private async Task<string> LongTask()
{
if(isInCache)
{
return cachedValue(); // cache value is a const string you can do return "1" instead.
}
// else do the long thing and return my Task<string>
return await DoSomethingLong();
}
However, in the cases where the result is cached, the async mechanism is redundant. This overhead is mostly negligible but you can improve performance by dropping both the async and await and create a completed task using Task.FromResult:
private Task<string> LongTask()
{
if(isInCache)
{
return Task.FromResult(cachedValue());
}
// else do the long thing and return my Task<string>
return DoSomethingLong();
}
...when you write “await someObject;” the compiler will generate code that checks whether the operation represented by someObject has already completed. If it has, execution continues synchronously over the await point. If it hasn’t, the generated code will hook up a continuation delegate to the awaited object such that when the represented operation completes, that continuation delegate will be invoked
From Async/Await FAQ
Task.Result doesn't execute the task synchronously, it waits synchronously. That means that the calling thread is blocked waiting for the task to complete. When you use that in an environment with a SynchronizationContext that may lead to a deadlock since the thread is blocked and can't handle the task's completion. You shouldn't use the Result property on a task that hasn't completed yet.