我试图在我的程序中使用async和await的概念。该程序突然退出。我试图从几个随机网址获取内容长度并处理它并显示每个网址的字节大小。
代码:
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;
}
}
}
主要
public static void Main(string[] args)
{
asyncclass asyncdemo = new asyncclass();
asyncdemo.MainCall();
}
答案 0 :(得分:4)
MainCall
返回未完成的任务,除此之外没有其他代码行,因此您的程序结束
等待它使用:
asyncdemo.MainCall().Wait();
您需要避免async void
并将MainCall
更改为async Task
,以便能够从来电者处等待。
由于这似乎是一个控制台应用程序,因此您无法使用当前版本的编译器将await
和async
用于Main
方法(我认为正在讨论即将在C#7中实施的feature。
答案 1 :(得分:3)
问题在于您没有等待异步方法,因此应用程序会在方法结束之前退出。
在c#7中,你可以创建一个async entry point,它允许你使用await关键字。
public static async Task Main(string[] args)
{
asyncclass asyncdemo = new asyncclass();
await asyncdemo.MainCall();
}
如果您想从MainCall
冒出异常,则需要将返回类型更改为Task
。
public async Task MainCall()
{
await SumPageSizes();
}
如果您想在c#7之前运行代码异步,则可以执行以下操作。
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();
}
答案 2 :(得分:0)
使用async void方法时必须非常小心。那些将不会被等待。异步void的一个常见示例是当您在按钮单击中调用等待方法时:
private async void Button_Click(object sender, RoutedEventArgs e)
{
// run task here
}
这样UI就不会等待按钮点击完成。 在大多数自定义方法中,您几乎总是希望返回一个Task,以便您能够知道方法何时完成。