先看看不使用Async,Await:
//创建计时器
private static readonly Stopwatch Watch = new Stopwatch();
private static void Main(string[] args)
{
test2();
}
//不使用Async、Await的同步
private static void test2()
{
Watch.Start();
const string url1 = "http://www.cnblogs.com/";
const string url2 = "https://www.csdn.net/";
//也可以这样 Task<int> t = Task.Factory.StartNew<int>(() => CountCharacters(1, url1));
Task<int> t1 = new Task<int>(() => CountCharacters(1, url1));
t1.Start();
Task<int> t2 = new Task<int>(() => CountCharacters(1, url2));
t2.Start();
for (var i = 0; i < 3; i++)
{
ExtraOperation(i + 1);
}
//控制台输出
Console.WriteLine("{" + url1 + "} 的字符个数:{" + t1.Result + "}");
Console.WriteLine("{" + url2 + "} 的字符个数:{" + t2.Result + "}");
Console.WriteLine("全部执行完成,使用时间:{" + Watch.ElapsedMilliseconds + "} ms");
Console.Read();
}
//同步
private static void test1()
{
//启动计时器
Watch.Start();
const string url1 = "http://www.cnblogs.com/";
const string url2 = "https://www.csdn.net/";
//两次调用 CountCharacters 方法(下载某网站内容,并统计字符的个数)
var result1 = CountCharacters(1, url1);
var result2 = CountCharacters(2, url2);
//三次调用 ExtraOperation 方法(主要是通过拼接字符串达到耗时操作)
for (var i = 0; i < 3; i++)
{
ExtraOperation(i + 1);
}
//控制台输出
Console.WriteLine("{" + url1 + "} 的字符个数:{" + result1 + "}");
Console.WriteLine("{" + url2 + "} 的字符个数:{" + result2 + "}");
Console.WriteLine("全部执行完成,使用时间:{" + Watch.ElapsedMilliseconds + "} ms");
Console.Read();
}
/// <summary>
/// 统计字符个数
/// </summary>
/// <param name="id"></param>
/// <param name="address"></param>
/// <returns></returns>
private static int CountCharacters(int id, string address)
{
var wc = new WebClient();
Console.WriteLine("开始调用 id = {"+id+"}:{"+Watch.ElapsedMilliseconds+"} ms");
var result = wc.DownloadString(address);
Console.WriteLine("调用完成 id = {"+id+"}:{"+Watch.ElapsedMilliseconds+"} ms");
return result.Length;
}
/// <summary>
/// 额外操作
/// </summary>
/// <param name="id"></param>
private static void ExtraOperation(int id)
{
//这里是通过拼接字符串进行一些相对耗时的操作
var s = "";
for (var i = 0; i < 6000; i++)
{
s += i;
}
Console.WriteLine("id = {" + id + "} 的 ExtraOperation 方法完成:{" + Watch.ElapsedMilliseconds + "} ms");
}
当执行test1()时,结果是:
当执行test2()时,结果是:
可以看出在调用CountCharacters方法时,若使用了new Task<int>(...)的方式去调用,达到了异步的效果。整个程序运行速度明显加快。程序主线程在需要CountCharacters的返回值的地方会阻塞程序,等待CountCharacters执行完成。
再改一下代码,使用Async、Await的方式:
class Program
{
//创建计时器
private static readonly Stopwatch Watch = new Stopwatch();
private static void Main(string[] args)
{
//启动计时器
Watch.Start();
const string url1 = "http://www.cnblogs.com/";
const string url2 = "https://www.csdn.net/";
//两次调用 CountCharacters 方法(下载某网站内容,并统计字符的个数)
var result1 = CountCharacters(1, url1);
var result2 = CountCharacters(2, url2);
//三次调用 ExtraOperation 方法(主要是通过拼接字符串达到耗时操作)
for (var i = 0; i < 3; i++)
{
ExtraOperation(i + 1);
}
//控制台输出
Console.WriteLine("{" + url1 + "} 的字符个数:{" + result1.Result + "}");
Console.WriteLine("{" + url2 + "} 的字符个数:{" + result2.Result + "}");
Console.WriteLine("全部执行完成,使用时间:{" + Watch.ElapsedMilliseconds + "} ms");
Console.Read();
}
/// <summary>
/// 统计字符个数
/// </summary>
/// <param name="id"></param>
/// <param name="address"></param>
/// <returns></returns>
private static async Task<int> CountCharacters(int id, string address)
{
var wc = new WebClient();
Console.WriteLine("开始调用 id = {" + id + "}:{" + Watch.ElapsedMilliseconds + "} ms");
var result = await wc.DownloadStringTaskAsync(address);
Console.WriteLine("调用完成 id = {" + id + "}:{" + Watch.ElapsedMilliseconds + "} ms");
return result.Length;
}
/// <summary>
/// 额外操作
/// </summary>
/// <param name="id"></param>
private static void ExtraOperation(int id)
{
//这里是通过拼接字符串进行一些相对耗时的操作
var s = "";
for (var i = 0; i < 6000; i++)
{
s += i;
}
Console.WriteLine("id = {" + id + "} 的 ExtraOperation 方法完成:{" + Watch.ElapsedMilliseconds + "} ms");
}
}
执行结果:
从结果来看,用了Task,速度确实是快了很多。大部分有返回值的方法,都可以考虑改成这样的方式去做。
而用不用Async、Await实际上区别不大。只是Async、Await有点语法糖的意思。
如果公司用的是VS2010这样的旧型IDE,或者你想写个方法,既能用于同步,又能用于异步的,那就不加Async、Await;
如果基本确定,就是要玩异步的,那就用Async、Await,看起来也挺直观。