我正在尝试编写我的第一个异步应用并确保其同时工作。问题是我同步写了相同的应用程序,我没有看到时差。
class Program
{
private static List<string> List1 = new List<string>();
Stopwatch s = new Stopwatch();
s.Start();
var waitOne = Load(1000);
Task.WhenAll(waitOne);
Console.WriteLine("Done Time:" + (s.ElapsedMilliseconds / 1000).ToString());
Console.ReadLine();
}
static async Task Load(int i)
{
for (int y = 0; y < i; y++)
{
List1.Add(callWcf(y).Result);
}
await Task.Yield();
}
static async Task<string> callWcf(int i)
{
string here;
using (ServiceReference1.Client client = new AsyncTests.ServiceReference1.Client())
{
here = client.GetThisInt(i);
}
await Task.Yield();
return here;
}
}
WCF服务是我通过此链接http://msdn.microsoft.com/en-us/library/bb386386.aspx;
构建的简单服务返回&#34;您输入了{0}&#34;
我同步执行相同的代码,并且它们都需要8秒进行1000次迭代,这很快但我认为我的异步是错误的,因为它应该比同步更快。我已经按照教程,听了几个播客,我知道我错过了什么,但我不知道是什么。
答案 0 :(得分:2)
我有async
intro你可能会觉得有帮助。
异步代码并不总是运行得更快。实际上,对异步代码的直接逐行转换通常运行较慢。异步代码的主要优点是并发性:它在异步操作正在进行时释放调用线程以执行其他工作。
要查看您的代码:
Task.WhenAll(waitOne);
这实际上并没有做任何事情。 WhenAll
将返回在Task
完成时完成的waitOne
,但会忽略从WhenAll
返回的任务。
List1.Add(callWcf(y).Result);
这里你的代码主演一个异步操作(callWcf
)然后转身并立即同步阻止等待它完成(Result
)。
await Task.Yield();
这段代码毫无意义。显然,只有那些使async
方法不包含await
的编译器警告静音。
here = client.GetThisInt(i);
此处代码再次同步阻塞。
正如我在async best practices article中所描述的那样,async
的原则之一就是“一直使用异步”。从最低级别(寻找任何基于I / O的东西)进行此操作最简单,并逐步完成。在这种情况下,最好的起点是WCF调用:
static async Task<string> CallWcfAsync(int i)
{
using (ServiceReference1.Client client = new AsyncTests.ServiceReference1.Client())
{
return await client.GetThisIntAsync(i);
}
}
我还更改了方法名称以匹配TAP conventions。
接下来,您将转到该方法的调用方:
static async Task Load(int i)
{
for (int y = 0; y < i; y++)
{
List1.Add(await CallWcfAsync(y));
}
}
或者如果您想同时执行多个呼叫:
static async Task LoadAsync(int i)
{
var tasks = Enumerable.Range(0, i).Select(y => CallWcfAsync(y));
List1.AddRange(await Task.WhenAll(tasks));
}
最后,您的Main
方法必须阻止任务;这是允许调用Result
或Wait
的非常罕见的情况之一:
LoadAsync(1000).Wait();