简体   繁体   中英

Run time error and Program exits when using - Async and await using C#

I am trying to use the concept of async and await in my program. The program abruptly exits. I am trying to get the content length from few random urls and process it 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;
        }
    }
}

Main

 public static void Main(string[] args)
        {
            asyncclass asyncdemo = new asyncclass();
            asyncdemo.MainCall();

        }

MainCall returns an uncompleted task and no other line of code is present beyond that, so your program ends

To wait for it use:

asyncdemo.MainCall().Wait();

You need to avoid async void and change MainCall to async Task in order to be able to wait for it from the caller.

Since this seems to be a console application, you can't use the await and async for the Main method using the current version of the compiler (I think the feature is being discussed for upcoming implementation in C# 7).

The problem is that you don't await an asynchron method and therefore you application exits before the method ended.

In c# 7 you could create an async entry point which lets you use the await keyword.

public static async Task Main(string[] args)
{
    asyncclass asyncdemo = new asyncclass();
    await asyncdemo.MainCall();
}

If you want to bubble your exceptions from MainCall you need to change the return type to Task .

public async Task MainCall() 
{
    await SumPageSizes();
}

If you wanted to run your code async before c# 7 you could 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();
}

You have to be very careful when using async void methods. Those will not be awaited. One normal example of an async void is when you are calling an awaitable method inside a button click:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    // run task here
}

This way the UI won't be stuck waiting for the button click to complete. On most custom methods you will almost always want to return a Task so that you are able to know when your method is finished.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM