1

我正在尝试将几个文件复制到一个共享文件夹(Aprox 20),但每个文件同时在不同的线程上。

我正在使用这样的代码来复制文件

AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);    
WindowsIdentity identity = new WindowsIdentity(username, password);
WindowsImpersonationContext context = identity.Impersonate();

try
{
    File.Copy(@"c:\temp\MyFile.txt", @"\\server\folder\Myfile.txt", true);
}
catch
{
    context.Undo();
}

但有些文件没有被复制,我得到的错误如下:

"No se pueden realizar más conexiones a esteequipo remoto en este momento, ya que hay más de las que puede aceptar"

翻译会是这样的

“此时无法与此远程计算机建立更多连接,因为它可以接受更多连接”

是否有另一种方法可以将文件复制到共享文件夹或明确关闭连接?

4

6 回答 6

3

Windows 工作站对它们可以同时接受的网络连接数有限制。

你可以:

  • 使用少于 20 个连接
  • 使用不同的文件复制协议,尽管您会遇到网络套接字数量的限制
  • 切换到使用没有此类限制的服务器操作系统
于 2011-02-21T17:42:16.243 回答
2

尝试通过同一线程复制文件。我确信每个连接有一个线程允许服务器达到其限制。

于 2011-02-21T17:41:26.073 回答
1

Windows 客户端操作系统受限于它们可以接受的并发连接数。即使这是一个服务器系统,Windows 文件共享也允许管理员限制共享的连接数。

您可能想要做的是将自己限制在几个同时线程中(3 到 5 个应该这样做)。将所有文件名放入队列中,并让每个线程出列(使用适当的锁定)下一个要处理的文件,直到队列为空。这称为生产者/消费者方案。作为奖励,无论如何,您最终可能会获得比同时完成所有 20 个更高的吞吐量,因为系统不必花更少的时间担心网络冲突和上下文切换。

于 2011-02-21T17:44:02.637 回答
0

另一种选择可能是使用网络驱动器 - 检查是否存在,并在必要时进行映射。映射和取消映射驱动器的代码可以在我的回答中找到:

映射驱动器后,无论线程如何,您的代码都应使用相同的连接。我们在 Web 服务调用中使用它,就其本质而言,它是多线程的,并且它是一种高度使用的服务,在高峰时间每分钟复制数百个文件。我相对肯定它会在你的情况下工作。

C# - 从 Web 服务映射网络驱动器

要检查驱动器是否已经映射,只需调用

if (System.IO.Directory.Exists(<drive letter here>));

编辑 - 添加代码以连接和断开网络驱动器

public static class NetworkDrives
    {
        public static bool  MapDrive(string DriveLetter, string Path, string Username, string Password)
        {

            bool ReturnValue = false;

            if(System.IO.Directory.Exists(DriveLetter + ":\\"))
            {
                DisconnectDrive(DriveLetter);
            }
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.RedirectStandardOutput = true;

            p.StartInfo.FileName = "net.exe";
            p.StartInfo.Arguments = " use " + DriveLetter + ": " + Path + " " + Password + " /user:" + Username;
            p.Start();
            p.WaitForExit();

            string ErrorMessage = p.StandardError.ReadToEnd();
            string OuputMessage = p.StandardOutput.ReadToEnd();
            if (ErrorMessage.Length > 0)
            {
                throw new Exception("Error:" + ErrorMessage);
            }
            else
            {
                ReturnValue = true;
            }
            return ReturnValue;
        }
        public static bool DisconnectDrive(string DriveLetter)
        {
            bool ReturnValue = false;
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.RedirectStandardOutput = true;

            p.StartInfo.FileName = "net.exe";
            p.StartInfo.Arguments = " use " + DriveLetter + ": /DELETE";
            p.Start();
            p.WaitForExit();

            string ErrorMessage = p.StandardError.ReadToEnd();
            string OuputMessage = p.StandardOutput.ReadToEnd();
            if (ErrorMessage.Length > 0)
            {
                throw new Exception("Error:" + ErrorMessage);
            }
            else
            {
                ReturnValue = true;
            }
            return ReturnValue;
        }

    }
于 2011-02-21T17:58:51.523 回答
0

请记住,IO 速度几乎总是一个瓶颈,因此您最好一次将传输限制为 1 或 2 个文件。您可能正在与磁盘读取或网络吞吐量挂钩。最好的办法是从 1 线程开始测量性能,并在传输速度和线程之间寻求平衡。

于 2011-02-21T17:42:01.810 回答
0

问题是每个线程都在建立自己的连接。如果你有更多的线程在运行,目标机器可以接受,你就会遇到这个问题。您需要找到一种方法来确保您不超过此限制。

是否有理由需要多线程?我确定答案是“是”,但如果您认为多线程将通过允许同时发生多个复制操作来加速复制操作,情况并非如此。只有这么多的 bamdwidth,目标 PC 只能以特定的速度读/写,所以通过尝试在多个线程上写入多个文件,实际上只是单独减慢每个文件的速度。

但是,如果我猜对了,并且多个线程还有另一个原因,那么让我提供一个替代方案:在本地写入文件并使用完全不同的进程复制文件。拥有一个可以复制文件的 Windows 服务或控制台应用程序,而您的 UI 线程和其他线程则继续他们的工作。添加中间人可能会增加一些额外的复杂性,但它仍然比试图找到一种方法来解决这个问题要简单。

另一种方法是必须跟踪线程,并确保线程数永远不会超过目标机器上可用的连接数,并且您必须担心连接到机器的其他进程,因此您无法真正计算在这种方法上,要么。

跟踪线程并正确锁定当然是可行的,但只需在本地编写文件并让外部程序进行文件传输就更容易编写,也更容易排除故障。

于 2011-02-21T17:43:44.417 回答