public async Task <VirtualFile> CopyFile(VirtualFile file, VirtualDirectory targetDirectory, Action <ProgressArgs> progressCallback, CancellationToken cancellationToken) { var fileEntry = getFileEntry(file); var filename = VirtualPath.GetFileName(file.Name);//get filename from full path if (fileEntry.DirectoryId == targetDirectory.Id) { filename = $"Copy {filename}"; } var idx = 0; while (targetDirectory.GetFiles(false, filename).Any()) { var name = VirtualPath.GetFileNameWithoutExtension(filename); var ext = VirtualPath.GetFileExtension(filename); filename = $"{name} ({++idx}).{ext}"; } var createdFile = targetDirectory.CreateFile(filename); using (var newFileStream = createdFile.Open(FileMode.Open, FileAccess.Write)) using (var sourceFileStream = file.Open(FileMode.Open, FileAccess.Read)) { newFileStream.SetLength(sourceFileStream.Length); var restBytes = sourceFileStream.Length; var buffer = BufferHelper.GetBuffer(sourceFileStream); var currentProgress = -1; while (restBytes > 0 && !cancellationToken.IsCancellationRequested) { try { var count = (int)(restBytes > buffer.Length ? buffer.Length : restBytes); var read = await sourceFileStream.ReadAsync(buffer, 0, count, cancellationToken); await newFileStream.WriteAsync(buffer, 0, count, cancellationToken); restBytes -= read; } catch (TaskCanceledException) { } //report progress var progress = sourceFileStream.GetProgress(); if (progress == currentProgress) { continue; } currentProgress = progress; var message = VirtualPath.GetFileName(createdFile.Name); var progressArgs = new CopyProgressArgs(progress, message) { Operation = Operation.Copying }; _synchronizationContext.Post(x => progressCallback?.Invoke((ProgressArgs)x), progressArgs); } } if (!cancellationToken.IsCancellationRequested) { return(createdFile); } Remove(createdFile); _directoryWatcherSource.RaiseDeleted(targetDirectory, file); return(createdFile); }