async
/ CopyToAsync
/ WriteAsync
应该ReadAsync
有一些功能。
我可以对它们await
进行操作,我的线程继续处理其他代码,当这些功能结束时,它们会通知我。
它们不会浪费CPU时间,我也不需要为它们打开另一个线程。
但是,当我想做一些我没有这个功能的async
工作时,比如删除文件。
我可以像这样包装这个函数:
public static class FileExtensions {
public static Task DeleteAsync(this FileInfo fi) {
return Task.Factory.StartNew(() => fi.Delete() );
}
}
并调用此函数,如:
FileInfo fi = new FileInfo(fileName);
await fi.DeleteAsync();
我想知道的是:
1 - 当我做这个包装器时会发生什么?
这将为此打开新线程(来自ThreadPool
)在等待此功能时浪费CPU时间?
真正的async
函数和这个包装器有什么不同?
2 - 我怎么知道我在C#上使用的函数在内核之前是否真的是async
函数?
谢谢!
答案 0 :(得分:3)
首先,您的包装器应该使用Task.Run
而不是StartNew
。 StartNew
is a dangerous, low-level API,你不应该使用它。
当我做这个包装器时会发生什么?
它将在线程池线程上运行delete-file操作。
这将为此(从ThreadPool)打开新线程,在等待此功能时浪费CPU时间?
没有; CPU不用于等待此I / O操作。线程池线程处于阻塞状态并从CPU中交换出来。
我称之为"假异步"因为它是出现异步的方法,但实际上只是阻塞线程池线程。
真正的异步函数和这个包装器有什么不同?
我在博客上详细解释了这一点,但其核心是pure async operations do not require a thread to be blocked。
我怎么知道我在C#上使用的函数在内核之前是否真的是异步函数?
你不能;你需要知道它的实现。
在某些情况下,您可以推断出它是否真的是异步。例如,Win32子系统不允许异步文件打开或删除,因此您可以推断出任何"异步"文件打开或删除操作不是真正的异步。