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

本文关键字:速度 服务器 文件 复制 | 更新日期: 2023-09-27 18:24:16

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

为了简化进一步的

  • C#应用程序在台式计算机上执行
  • 原始文件在服务器1上
  • 文件要复制到服务器2
  • Server3包含数据库

当我在桌面上运行这个程序时,除了server1之外,其他一切都很好,它似乎在大约5分钟后几乎变成了holt,尽管复制过程在5分钟后仍能正常工作。任何其他尝试连接到该服务器的应用程序/用户都无法连接。

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

我甚至尝试过使用sleep,因为我认为速度减慢是因为服务器1上的网络活动过多和/或磁盘I/O活动过多。sleep没有提供任何帮助,同样的问题还在继续。所以我猜这个问题的发生还有其他原因。

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

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

为什么会发生这种情况?

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

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

在Windows Vista或更高版本上,可以通过为CopyFileEx() Windows API函数指定COPY_FILE_NO_BUFFERING来避免使用缓冲。

您可以指定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);

也许值得一试,看看它是否有帮助。