我正在处理一个文件组织者应用程序。这些文件定期为500MB至2GB。一切正常,但是应用程序“停止响应”是非常烦人的。我想做的是每次读取/写入操作之后的字节或MEG by Meg by Meg by Meg copy。沿着这些台词,我不知道要使用的实际课程是什么,所以我只是要做一些东西:)

private void CopyFile(string inFilename, string outFilename)
{
    FileReader inReader(inFilename);
    FileWriter outWriter(outFilename, FileMode.OpenOrCreate);

    byte theByte;
    while (theByte = inReader.ReadByte())
    {
        outWriter.WriteByte(theByte, WriteMode.Append);
        UpdateProgressBar();
        Application.DoEvents();
    }

    inReader.CloseFile();
    outWriter.CloseFile();
}

我知道这似乎是一件简单的事情,但是我一生中似乎找不到任何类型的例子,而无需使用直接的API呼叫或其他任何事情。我必须在这里缺少一些东西,所以如果有人可以让我走上正确的轨道,我将非常感谢。

提前致谢!

有帮助吗?

解决方案

你应该使用 背景工作者 在您的表格上进行复制。它将允许文件副本在单独的线程上完成,并让您的UI响应。还有一些复杂的复杂性,但是背景工作者为您服务了很多管道。但是,有很多 例子你想做什么.

其他提示

您需要使用 BackownWorkerThread 实现这一目标。这是一个很好的例子: 使用背景工人线程复制文件

我想用 CopyFileEx 功能。如果在托管框架库中不存在对该功能的模拟,则无论如何如何使用它:也许是类似的文章 http://www.thetechscene.com/2008/09/copyfileex-with-progress-callback-inback-in-cusing-pinvoke/

我想使用的原因 CopyFileEx 是我认为它是在O/S内核中实现的,数据将在文件系统驱动程序中从一个文件复制到另一个文件,而无需使用用户存储器(更不用说托管内存)了。

threading.threadpool.queueuserworkitem应该让您走得好。

一种方法是在单独的线程中执行复制操作。当线程执行复制文件的工作时,您的主要应用程序将继续正常运行。当然,您想在线程和主应用程序之间添加通信,以便您可以更新进度栏或类似的反馈机制。

如果您不想处理多个线程,另一种方法是创建一个包含复制操作状态变量的类,以及一个从主应用程序定期调用的成员函数,以便每次称为一个字节。

除了运行背景线程外,您还应注意,您正在复制512m-2g的数据 一次一个字节. 。这将最多转化为2 十亿 打电话给ReadByte和WriteByte。希望那些电话缓冲区在某个地方,所以您不会做2 十亿 设法进行了不受管理的过渡,但即使如此,肯定会加起来。

记忆不是免费的,但这是肯定的,因为他们很便宜。分配一个缓冲区(也许是16k-64k),并将其复制成块。不,该代码并不像您需要处理一个不读取整个块的情况那样简单,但是我宁愿在2G上使用2G/64K方法调用。

您在这里有两个问题。首先是GUI线程在复制大文件时没有响应。您应该使用背景线程来解决该问题,如其他人所建议的。

另一个问题是您当前的文件复制例程不支持进度回调函数。以下问题的公认答案具有您编写自己的解决方案所需的信息:

我可以使用.net中的fileInfo.copyto()显示文件复制进度吗?

编辑:我刚刚找到了这个 CopyFileex的包装类. 。我测试了它,效果很好!

using System;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;

namespace FileCopyTest {
    public sealed class FileRoutines {
        public static void CopyFile(FileInfo source, FileInfo destination) {
            CopyFile(source, destination, CopyFileOptions.None);
        }

        public static void CopyFile(FileInfo source, FileInfo destination,
            CopyFileOptions options) {
            CopyFile(source, destination, options, null);
        }

        public static void CopyFile(FileInfo source, FileInfo destination,
            CopyFileOptions options, CopyFileCallback callback) {
            CopyFile(source, destination, options, callback, null);
        }

        public static void CopyFile(FileInfo source, FileInfo destination,
            CopyFileOptions options, CopyFileCallback callback, object state) {
            if (source == null) throw new ArgumentNullException("source");
            if (destination == null)
                throw new ArgumentNullException("destination");
            if ((options & ~CopyFileOptions.All) != 0)
                throw new ArgumentOutOfRangeException("options");

            new FileIOPermission(
                FileIOPermissionAccess.Read, source.FullName).Demand();
            new FileIOPermission(
                FileIOPermissionAccess.Write, destination.FullName).Demand();

            CopyProgressRoutine cpr = callback == null ?
                null : new CopyProgressRoutine(new CopyProgressData(
                    source, destination, callback, state).CallbackHandler);

            bool cancel = false;
            if (!CopyFileEx(source.FullName, destination.FullName, cpr,
                IntPtr.Zero, ref cancel, (int)options)) {
                throw new IOException(new Win32Exception().Message);
            }
        }

        private class CopyProgressData {
            private FileInfo _source = null;
            private FileInfo _destination = null;
            private CopyFileCallback _callback = null;
            private object _state = null;

            public CopyProgressData(FileInfo source, FileInfo destination,
                CopyFileCallback callback, object state) {
                _source = source;
                _destination = destination;
                _callback = callback;
                _state = state;
            }

            public int CallbackHandler(
                long totalFileSize, long totalBytesTransferred,
                long streamSize, long streamBytesTransferred,
                int streamNumber, int callbackReason,
                IntPtr sourceFile, IntPtr destinationFile, IntPtr data) {
                return (int)_callback(_source, _destination, _state,
                    totalFileSize, totalBytesTransferred);
            }
        }

        private delegate int CopyProgressRoutine(
            long totalFileSize, long TotalBytesTransferred, long streamSize,
            long streamBytesTransferred, int streamNumber, int callbackReason,
            IntPtr sourceFile, IntPtr destinationFile, IntPtr data);

        [SuppressUnmanagedCodeSecurity]
        [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool CopyFileEx(
            string lpExistingFileName, string lpNewFileName,
            CopyProgressRoutine lpProgressRoutine,
            IntPtr lpData, ref bool pbCancel, int dwCopyFlags);
    }

    public delegate CopyFileCallbackAction CopyFileCallback(
        FileInfo source, FileInfo destination, object state,
        long totalFileSize, long totalBytesTransferred);

    public enum CopyFileCallbackAction {
        Continue = 0,
        Cancel = 1,
        Stop = 2,
        Quiet = 3
    }

    [Flags]
    public enum CopyFileOptions {
        None = 0x0,
        FailIfDestinationExists = 0x1,
        Restartable = 0x2,
        AllowDecryptedDestination = 0x8,
        All = FailIfDestinationExists | Restartable | AllowDecryptedDestination
    }
}

您真正想做的是拥有一个多线程应用程序,并在背景线程中执行文件副本,这样您的主线程就不会被绑定。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top