Runtime error and program exit when using - Async and await using C #
I am trying to use the concept of async and wait in my program. The program exits abruptly. I am trying to get content length from multiple random urls and process them and display the size in bytes of each url.
Code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
namespace TestProgram
{
public class asyncclass
{
public async void MainCall() {
await SumPageSizes();
}
public async Task SumPageSizes(){
List<string> urllist = GetUrlList();
foreach (var url in urllist)
{
byte[] content = await GetContent(url);
Displayurl(content, url);
}
}
private void Displayurl(byte[] content, string url)
{
var length = content.Length;
Console.WriteLine("The bytes length for the url response " + url + " is of :" +length );
}
private async Task<byte[]> GetContent(string url)
{
var content = new MemoryStream();
try
{
var obj = (HttpWebRequest)WebRequest.Create(url);
WebResponse response = obj.GetResponse();
using (Stream stream = response.GetResponseStream())
{
await stream.CopyToAsync(content);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
return content.ToArray();
}
private List<string> GetUrlList()
{
var urllist = new List<string>(){
"http://msdn.microsoft.com/library/windows/apps/br211380.aspx",
"http://msdn.microsoft.com",
"http://msdn.microsoft.com/en-us/library/hh290136.aspx",
"http://msdn.microsoft.com/en-us/library/ee256749.aspx",
"http://msdn.microsoft.com/en-us/library/hh290138.aspx",
"http://msdn.microsoft.com/en-us/library/hh290140.aspx",
"http://msdn.microsoft.com/en-us/library/dd470362.aspx",
"http://msdn.microsoft.com/en-us/library/aa578028.aspx",
"http://msdn.microsoft.com/en-us/library/ms404677.aspx",
"http://msdn.microsoft.com/en-us/library/ff730837.aspx"
};
return urllist;
}
}
}
home
public static void Main(string[] args)
{
asyncclass asyncdemo = new asyncclass();
asyncdemo.MainCall();
}
The problem is that you are not expecting an asynchronous method and therefore you terminate the application before the method completes.
In C # 7, you can create an async entry point that allows the wait keyword.
public static async Task Main(string[] args)
{
asyncclass asyncdemo = new asyncclass();
await asyncdemo.MainCall();
}
If you want to bubble your exceptions out MainCall
, you need to change the return type to Task
.
public async Task MainCall()
{
await SumPageSizes();
}
If you want to run asynchronous code before C # 7, you can do the following.
public static void Main(string[] args)
{
asyncclass asyncdemo = new asyncclass();
asyncdemo.MainCall().Wait();
// or the following line if `MainCall` doesn't return a `Task`
//Task.Run(() => MainCall()).Wait();
}
MainCall
returns an unfinished task and there is no other line of code besides it, so your program ends
Expect to use:
asyncdemo.MainCall().Wait();
You need to avoid async void
and change MainCall
to async Task
to be able to wait for it from the caller.
Since it is similar to a console application, you can not use await
, and async
for the method of Main
using the current version of the compiler (I think the discussion for the upcoming implementation of C # 7).
You have to be very careful when using async void methods. They don't wait. One normal example of asynchronous void is when you call an expected method inside a button click:
private async void Button_Click(object sender, RoutedEventArgs e)
{
// run task here
}
This way, the UI won't get stuck waiting for the button click to complete. In most custom methods, you almost always want to return a task so you can know when your method has completed.