【发布时间】:2017-07-13 05:30:54
【问题描述】:
为什么下面的代码会导致:
public static class Program
{
public static void Main(params string[] args)
{
var sourceFileName = @"C:\Users\ehoua\Desktop\Stuff\800MFile.exe";
var destinationFileName = sourceFileName + ".bak";
FileCopyAsync(sourceFileName, destinationFileName);
// The line below is actually faster and a lot less CPU-consuming
// File.Copy(sourceFileName, destinationFileName, true);
Console.ReadKey();
}
public static async void FileCopyAsync(string sourceFileName, string destinationFileName, int bufferSize = 0x1000, CancellationToken cancellationToken = default(CancellationToken))
{
using (var sourceFile = File.OpenRead(sourceFileName))
{
using (var destinationFile = File.OpenWrite(destinationFileName))
{
Console.WriteLine($"Copying {sourceFileName} to {destinationFileName}...");
await sourceFile.CopyToAsync(destinationFile, bufferSize, cancellationToken);
Console.WriteLine("Done");
}
}
}
}
而 File.Copy(): https://msdn.microsoft.com/en-us/library/system.io.file.copy(v=vs.110).aspx 的 CPU 消耗要少得多:
那么,使用 async / await 来复制文件还有真正的兴趣吗?
我认为保存用于复制的线程可能值得,但 File.Copy 窗口功能似乎在 CPU 百分比方面赢得了胜利。有些人会争辩说这是因为真正的 DMA 支持,但是,我是否在做任何事情来破坏表演?或者有什么办法可以通过我的异步方法提高 CPU 使用率?
【问题讨论】:
-
这可能与实现
File.Copy的一些底层方式与使用File.OpenRead和File.OpenWrite的直接基于流的方法之间的区别有关。我怀疑它与同步与异步有什么关系。 -
就像我说的,我怀疑它是否与异步有关,而是与 如何 执行复制操作有关。您的 async 方法从一个流复制到另一个流,而您的 sync 方法使用
File.Copy包装本机 Win32 操作以实现更底层的方法。见stackoverflow.com/questions/1246899/… -
您的问题是:我要求编译器在等待 IO 操作时生成可以利用 CPU 的代码;为什么我这样做的时候 CPU 使用率更高? 当你这样说的时候问题就自己回答了,不是吗?你认为异步是 for 的什么?这是为了增加等待 IO 时使用的 CPU 量。请记住,CPU 利用率高是好的。人们说它很糟糕,但高 CPU 很棒。机器所有者为该 CPU 付费;它空闲的每一毫秒都是一种资源的浪费。
-
好吧,也许这里发生了其他事情;正如其他人所说,您可能会从病毒检查程序或其他东西中获得一些短暂的影响。特别是因为您的程序在等待时似乎没有做任何事情。但总的来说,您应该期望在使用异步时看到 更好 -- 更高 -- CPU 利用率。不要停止 CPU;继续努力解决 CPU 密集型问题。
-
@TheodorZoulias:是的,正如我在评论中提到的,我们想要的是 CPU 高效地工作以完成 CPU 密集型工作。虽然我们很挑剔,但我注意到 Windows 上的 .NET 线程需要 1MB 的已提交虚拟地址空间;操作系统足够聪明,除非必要,否则不会将其映射到 RAM。大多数情况下,最好将其视为 1MB 的交换文件,而不是 RAM。
标签: c# .net asynchronous io file-copying