2014-09-24 47 views
3

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

为了简化进一步

  • C#应用程序在桌面计算机
  • 原始文件在Server1上执行
  • 文件将被复制到Server2
  • Server3的包含数据库

当我在我的桌面上运行这个程序时,一切正常,除了server1,这似乎almos即使5分钟后复印过程仍能继续良好地工作,但大约5分钟后仍会磨成碎片。任何其他尝试连接到该服务器的应用程序/用户都不能。

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

我甚至尝试过使用sleep,因为我认为减速是因为网络活动过多和/或server1上的磁盘I/O活动过多。 sleep没有任何帮助,同样的问题仍然存在。所以我猜猜这个问题是出于其他原因。

我使用类似下面的代码复制文件

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

这究竟是为什么?

+0

如何复制文件?如果你只是在做一堆连续的文件副本,听起来就像你的服务器只是不足够的。如果你想要并行运行多个副本,那么你应该把你的代码构造成不那么激进。 – 2014-09-24 11:47:33

+0

我正在复制基于数据库查询的特定文件。不是平行复制,它一次复制1个文件。 – oshirowanen 2014-09-24 11:48:06

+0

这不能回答我的问题。你能显示一些代码吗? – 2014-09-24 11:48:36

回答

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); 

这可能值得尝试一下,看看它是否有帮助。

+0

@oshirowanen它只是想在前一行定义一个'int cancel = 0;'。(我会更新示例) – 2014-09-25 10:59:50

+0

代码正在工作,但仍然会导致原始问题,即大约5分钟后,需要server1的所有应用程序/用户开始放慢速度,直到我停止从桌面运行复制应用程序。 – oshirowanen 2014-09-25 11:18:58

+0

@oshirowanen嗯,这是值得一试。您是否阅读过我在答复开始时引用的文章 - 它确实提出了其他一些内容。 – 2014-09-25 12:03:54

相关问题