之前我发布了一个关于在客户端或服务端应用 Async-Await 的问题,你需要先阅读那个问题再来看这个问题,因为这两个问题是紧密相关的。问题链接:https://dev59.com/h2jWa4cB1Zd3GeqPvveY
根据答案,我已经测试了 C# 4.0(TPL)和 C# 5.0(Async - Await)的代码。我使用异步和同步方法调用服务,并比较了每种情况下使用的线程数。
以下是我用于测试资源使用情况的代码:
主要方法
List<Task<string>> tasksList = new List<Task<string>>();
List<int> asyncThreads = new List<int>();
List<int> tplThreads = new List<int>();
Stopwatch watch = new Stopwatch();
watch.Start();
// Call the Async version of the method
for (int i = 0; i < 500; i++)
{
tasksList.Add(GetNameFromServiceAsync("Input" + i.ToString(), asyncThreads));
}
Task.WaitAll(tasksList.ToArray());
watch.Stop();
foreach (var item in asyncThreads.Distinct())
{
Console.WriteLine(item);
}
Console.WriteLine("(C# 5.0)Asynchrony Total Threads = " + asyncThreads.Distinct().Count());
Console.WriteLine(watch.ElapsedMilliseconds.ToString());
watch.Restart();
tasksList.Clear();
// Call the normal method
for (int i = 0; i < 500; i++)
{
tasksList.Add(GetNameFromService("Input" + i.ToString(), tplThreads));
}
Task.WaitAll(tasksList.ToArray());
watch.Stop();
foreach (var item in tplThreads.Distinct())
{
Console.WriteLine(item);
}
Console.WriteLine("(C# 4.0)TPL Total Threads" + tplThreads.Distinct().Count());
Console.WriteLine(watch.ElapsedMilliseconds.ToString());
异步和同步调用服务
static async Task<string> GetNameFromServiceAsync(string name, List<int> threads)
{
Console.WriteLine(" Start Current Thread : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
var task = await client.GetNameAsync(name);
threads.Add(System.Threading.Thread.CurrentThread.ManagedThreadId);
// Console.WriteLine("End GetNameFromServiceAsync Current Thread : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
return task;
}
static Task<string> GetNameFromService(string name, List<int> threads)
{
var task = Task<string>.Factory.StartNew(() =>
{
threads.Add(System.Threading.Thread.CurrentThread.ManagedThreadId);
// Console.WriteLine("GetNameFromService Current Thread : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
return client.GetName(name);
});
return task;
}
现在我已经研究了答案,并得出以下结果:
- 如果我对服务进行500次调用,它只使用4-5个线程。
- TPL调用会产生大约44-45个线程。
- 异步调用的时间约为17-18秒
- TPL调用的时间约为42-45秒。
编辑:
Q. 我的观察结论是,如果我们使用Async-Await而不是TPL的Task.Factory.startNew,那么它将消耗更少的线程。这正确吗?如果不是,那么应该如何进行比较?
Q. 因为我正在学习async-await,所以我想通过某种比较和可靠的代码来证明它的价值。