我刚刚对同步和异步进行了一些测试,并编写了以下程序进行测试。 也许我做错了什么或者我没有正确地理解异步,
我发现同步版本需要318 ms
而异步需要18764 ms
static void Main(string[] args)
{
int num = 25;
Task[] tasks = new Task[num];
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < num; i++)
{
int c = i;
tasks[i] = Task.Factory.StartNew(() => { RunAsync(c).Wait(); });
}
Task.WaitAll(tasks);
sw.Stop();
Console.WriteLine($"FINISHED (Async) in {sw.ElapsedMilliseconds} ms");
sw.Start();
for (int i = 0; i < num; i++)
{
RunSync(i + 100);
}
sw.Stop();
Console.WriteLine($"FINISHED (Sync) in {sw.ElapsedMilliseconds} ms");
Console.ReadLine();
}
private static void RunSync(int index)
{
FileStream stream = new FileStream(@"c:\\test\ff\tests.txt", FileMode.Open, FileAccess.Read, FileShare.Read);
string pp = Path.Combine(@"c:\\test\ff", "threadS-" + index + ".txt");
FileStream sw = File.Create(pp);
byte[] buffer = new byte[1024];
long bytesRead = 0;
long bytestoRead = stream.Length;
try
{
while (bytesRead < bytestoRead)
{
int count = stream.Read(buffer, 0, buffer.Length);
bytesRead += count;
sw.Write(buffer, 0, count);
}
}
finally
{
sw.Close();
stream.Close();
}
}
private async static Task RunAsync(int index)
{
FileStream stream = new FileStream(@"c:\\test\ff\tests.txt", FileMode.Open, FileAccess.Read, FileShare.Read);
int tId = Thread.CurrentThread.ManagedThreadId;
string pp = Path.Combine(@"c:\\test\ff", "thread-" + index + ".txt");
FileStream sw = File.Create(pp);
byte[] buffer = new byte[1024];
long bytesRead = 0;
long bytestoRead = stream.Length;
try
{
while (bytesRead < bytestoRead)
{
int count = await stream.ReadAsync(buffer, 0, buffer.Length);
bytesRead += count;
await sw.WriteAsync(buffer, 0, count);
}
}
finally
{
sw.Close();
stream.Close();
}
}
答案 0 :(得分:2)
有些事情你做得不正确,而且你开始时是错误的前提。所以让我从错误的前提开始:
async
/await
旨在让应用响应或在多个核心之间分配工作 - 它们不一定能提高运行时性能。
换句话说,当您查看整体吞吐量时,您可能会处理比连续处理工作单元更多的工作。但是,该阈值将随着在任何给定时间完成的工作量而变化。
正确处理async
/ await
意味着不要将较旧的Task
功能与较新的支持混合使用。这会丢失异步函数的所有好处并增加同步开销。 当您要等待后台工作完成时,切勿致电Task.Wait()
或Task.WaitAll(tasks)
。这会强制一个线程完全暂停并且无响应,直到后台工作完成。
您想进行以下调整:
for (int i = 0; i < num; i++)
{
int c = i;
tasks[i] = RunAsync(c);
}
await Task.WhenAll(tasks);
由于您无法使Main
函数成为async
,您可能必须将该调用移至另一个函数,以便您可以执行async / await协议。
答案 1 :(得分:1)
异步调用不一定有保证的执行时间。当调度程序决定资源可用时,它们将被调用。因此,完成它们的等待时间可能高于同步调用同一方法,因为保证在被调用时实时执行同步调用。