复制文件时服务器速度减慢

时间:2014-09-24 11:30:50

标签: c# .net c#-4.0 .net-4.0

我有一个C#程序,它查询数据库(server3)以确定用户所在的文件,然后将这些文件从(server1)复制到(server2)。

进一步简化

  • C#应用程序在台式计算机上执行
  • 原始文件位于server1
  • 将文件复制到server2
  • Server3包含数据库

当我在桌面上运行这个程序时,一切正常,除了server1,即使复制过程在5分钟后继续正常工作,它似乎在大约5分钟之后几乎磨成了hol。尝试连接到该服务器的任何其他应用程序/用户都可以

他们只是得到一个旋转光标,只有当我停止在桌面上运行程序时才会停止。在复制过程的前5分钟,一切都很好。当超过5分钟范围时,文件将继续复制,但是当其他人开始遇到与server1的连接问题时。

我甚至尝试使用sleep,因为我认为减速是因为网络活动过多和/或server1上的磁盘I / O活动过多。 sleep没有任何帮助,同样的问题还在继续。所以我猜测问题是由于其他原因而发生的。

我正在使用与此类似的代码来复制文件

while (reader1.read(){
    // system.threading.thread.sleep(2000);
    system.io.file.copy(source, destination);
}

为什么会这样?

1 个答案:

答案 0 :(得分:2)

根据this article,,减速的主要原因是文件副本使用缓冲。

在Windows Vista或更高版本中,通过将COPY_FILE_NO_BUFFERING指定给CopyFileEx() Windows API function,可以避免使用缓冲。

您可以按如下方式指定P / Invoke:

enum CopyProgressResult: uint
{
    PROGRESS_CONTINUE = 0,
    PROGRESS_CANCEL   = 1,
    PROGRESS_STOP     = 2,
    PROGRESS_QUIET    = 3
}

enum CopyProgressCallbackReason: uint
{
    CALLBACK_CHUNK_FINISHED = 0x00000000,
    CALLBACK_STREAM_SWITCH  = 0x00000001
}

delegate CopyProgressResult CopyProgressRoutine(
    long TotalFileSize,
    long TotalBytesTransferred,
    long StreamSize,
    long StreamBytesTransferred,
    uint dwStreamNumber,
    CopyProgressCallbackReason dwCallbackReason,
    IntPtr hSourceFile,
    IntPtr hDestinationFile,
    IntPtr lpData);

[Flags]
enum CopyFileFlags: uint
{
    COPY_FILE_FAIL_IF_EXISTS              = 0x00000001,
    COPY_FILE_RESTARTABLE                 = 0x00000002,
    COPY_FILE_OPEN_SOURCE_FOR_WRITE       = 0x00000004,
    COPY_FILE_ALLOW_DECRYPTED_DESTINATION = 0x00000008,
    COPY_FILE_COPY_SYMLINK                = 0x00000800, //NT 6.0+
    COPY_FILE_NO_BUFFERING                = 0x00001000
}

[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CopyFileEx
(
    string lpExistingFileName,
    string lpNewFileName,
    CopyProgressRoutine lpProgressRoutine, 
    IntPtr lpData,
    ref Int32 pbCancel,
    CopyFileFlags dwCopyFlags
);

然后像这样调用它(替换你自己的文件名);

int cancel = 0;
CopyFileEx(@"C:\tmp\test.bin", @"F:\test.bin", null, IntPtr.Zero, ref cancel, CopyFileFlags.COPY_FILE_NO_BUFFERING);

尝试这个并看看它是否有帮助可能是值得的。