csa*_*aam 48
异步编程的想法是允许调用线程(假设它是一个线程池线程)返回到线程池,以便在异步IO完成时用于某些其他任务.在引擎盖下,调用上下文被填充到数据结构中,并且一个或多个IO完成线程监视等待完成的调用.当IO完成完成时,线程将调用回到恢复调用上下文的线程池.这种方式而不是100个线程阻塞只有完成线程和几个线程池线程坐在大多数空闲.
我能想到的最好的是:
public async Task CopyFileAsync(string sourcePath, string destinationPath)
{
using (Stream source = File.Open(sourcePath))
{
using(Stream destination = File.Create(destinationPath))
{
await source.CopyToAsync(destination);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我没有对此进行过广泛的性能测试.我有点担心,因为如果它很简单就已经存在于核心库中了.
等待我在幕后所做的事情.如果你想了解它是如何工作的,那么理解Jeff Richter的AsyncEnumerator可能会有所帮助.它们可能不是完全相同的线,但想法非常接近.如果您从"异步"方法查看调用堆栈,您将在其上看到MoveNext.
就移动而言,它不需要是异步的,如果它真的是"移动"而不是副本然后删除.Move是对文件表的快速原子操作.如果您不尝试将文件移动到其他分区,它只会以这种方式工作.
Dre*_*kes 26
这是一个异步文件复制方法,它给出了我们正在按顺序读取和写入的操作系统提示,以便它可以预读取读取数据并为写入做好准备:
public static async Task CopyFileAsync(string sourceFile, string destinationFile)
{
using (var sourceStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous | FileOptions.SequentialScan))
using (var destinationStream = new FileStream(destinationFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, 4096, FileOptions.Asynchronous | FileOptions.SequentialScan))
await sourceStream.CopyToAsync(destinationStream);
}
Run Code Online (Sandbox Code Playgroud)
您也可以尝试缓冲区大小.这是4096字节.
Gre*_*egC 11
我稍微增强了@DrewNoakes的代码(性能和取消):
public static async Task CopyFileAsync(string sourceFile, string destinationFile, CancellationToken cancellationToken)
{
var fileOptions = FileOptions.Asynchronous | FileOptions.SequentialScan;
var bufferSize = 4096;
using (var sourceStream =
new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, fileOptions))
using (var destinationStream =
new FileStream(destinationFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, bufferSize, fileOptions))
await sourceStream.CopyToAsync(destinationStream, bufferSize, cancellationToken)
.ConfigureAwait(continueOnCapturedContext: false);
}
Run Code Online (Sandbox Code Playgroud)
虽然在某些情况下您需要避免Task.Run,但是Task.Run(() => File.Move(source, dest)会有效.值得考虑的是因为当文件只是在同一磁盘/卷中移动时,它几乎是瞬时操作,因为标题被更改但文件内容不会被移动.各种"纯"异步方法总是复制流,即使没有必要这样做,因此在实践中可能会慢得多.
您可以使用异步委托
public class AsyncFileCopier
{
public delegate void FileCopyDelegate(string sourceFile, string destFile);
public static void AsynFileCopy(string sourceFile, string destFile)
{
FileCopyDelegate del = new FileCopyDelegate(FileCopy);
IAsyncResult result = del.BeginInvoke(sourceFile, destFile, CallBackAfterFileCopied, null);
}
public static void FileCopy(string sourceFile, string destFile)
{
// Code to copy the file
}
public static void CallBackAfterFileCopied(IAsyncResult result)
{
// Code to be run after file copy is done
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将其命名为:
AsyncFileCopier.AsynFileCopy("abc.txt", "xyz.txt");
Run Code Online (Sandbox Code Playgroud)
此链接告诉您asyn编码的不同技术
您可以按照本文的建议执行此操作:
public static void CopyStreamToStream(
Stream source, Stream destination,
Action<Stream, Stream, Exception> completed)
{
byte[] buffer = new byte[0x1000];
AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(null);
Action<Exception> done = e =>
{
if(completed != null) asyncOp.Post(delegate
{
completed(source, destination, e);
}, null);
};
AsyncCallback rc = null;
rc = readResult =>
{
try
{
int read = source.EndRead(readResult);
if(read > 0)
{
destination.BeginWrite(buffer, 0, read, writeResult =>
{
try
{
destination.EndWrite(writeResult);
source.BeginRead(
buffer, 0, buffer.Length, rc, null);
}
catch(Exception exc) { done(exc); }
}, null);
}
else done(null);
}
catch(Exception exc) { done(exc); }
};
source.BeginRead(buffer, 0, buffer.Length, rc, null);
Run Code Online (Sandbox Code Playgroud)
jrh*_*ath -7
正确的复制方式:使用单独的线程。
您可能会这样做(同步):
//.. [code]
doFileCopy();
// .. [more code]
Run Code Online (Sandbox Code Playgroud)
以下是异步执行的方法:
// .. [code]
new System.Threading.Thread(doFileCopy).Start();
// .. [more code]
Run Code Online (Sandbox Code Playgroud)
这是一种非常幼稚的做事方式。如果做得好,该解决方案将包括一些事件/委托方法来报告文件副本的状态,并通知重要事件,例如失败、完成等。
干杯,jrh
| 归档时间: |
|
| 查看次数: |
57213 次 |
| 最近记录: |