C# 中的共享文件夹连接数过多问题

发布于 2024-10-18 10:42:05 字数 736 浏览 3 评论 0原文

我正在尝试将多个文件复制到共享文件夹(大约 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 este Equipment remoto en este momento, ya que hay más de las que puede aceptar”

翻译过来会是这样的

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

是否有其他方法将文件复制到共享文件夹或显式关闭连接?

I'm trying to copy several files to a shared folder (Aprox 20), but each file simultaneously on different threads.

I'm using a Code like this to copy the file

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

but some of the files don't get copied and the error that I get is the following:

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

Translated would be something like

"No more connections can be made to this remote computer at this time, as there are more connections that it can accept"

Is there another way to copy the file to the shared folder or to explicity close the connection?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

绝情姑娘 2024-10-25 10:42:05

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

您可以:

  • 使用少于 20 个连接
  • 使用不同的文件复制协议,尽管随后您将遇到网络套接字数量的限制
  • 切换到使用没有此类限制的服务器操作系统

Windows workstations have a limit on the number of network connections they can accept concurrently.

You could:

  • Use fewer than 20 connections
  • Use a different file copy protocol, although you'll then run into the limit on the number of network sockets
  • Switch to using a server OS, where there is no such limit
遗忘曾经 2024-10-25 10:42:05

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

Try copying the files over the same thread. I'm sure having one thread per connection is allowing the server to hit its limit.

吻风 2024-10-25 10:42:05

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

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

Windows client operating systems are limited to the number of concurrent connections they can accept. Even if this is a server system, Windows file sharing also allows the administrator to limit the number of connections to the share.

What you probably want to do is limit yourself to just a few simultaneous threads (3 to 5 ought to do it). Put all the filenames into a queue and have each thread dequeue (with appropriate locking) the next file to process until the queue is empty. This is called a producer/consumer scheme. As a bonus, you'll likely end up with more throughput than doing all 20 at once anyway, because the system has to spend less time worrying about network collisions and context switches.

将军与妓 2024-10-25 10:42:05

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

Well remember that IO speeds are almost always a bottleneck so you may be better off limiting the transfer to 1 or 2 files at a time. You are probably pegging either the disk reads or network throughput. Your best bet is to measure performance starting from 1 Thread and seek a balance of transfer speed and Threads.

醉态萌生 2024-10-25 10:42:05

问题是每个线程都在建立自己的连接。如果您运行的线程数量多于目标计算机可以接受的数量,您将遇到此问题。您需要找到一种方法来确保不超过此限制。

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

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

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

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

The issue is that each thread is making its own connection. If you have more threads running thatn te target machine can accept, you will run into this problem. You need to find a way to ensure that you don't exceed this limit.

Is there a reason this needs to be multi-threaded? I'm sure the answer is "yes", but just in case you're thinking that multi-threading is going to speed up the copy operations by allowing multiple copy operations to happen at once, this is not the case. There is only so much bamdwidth, and the target PC will only be able to read/write at a specific speed, so by trying to write multiple files at multiple threads, you'd actually just be slowing down each file individually.

If I'm guessing right, however, and there is another reason for multiple threads, then let me offer an alternative: Write the files locally and have a completely different process copy files over. Have a Windows Service or a Console application that can copy the files, while your UI thread and other threads go about their work. Adding a middle-man may add a bit of extra complexisty, but it's still simpler than trying to find a way to make this problem go away.

The alternative would be to have to keep track of threads, and ensure that the number of threads never exceeds the number of connections available onteh target machine, AND you have to worry about other processes connecting to the machine, so you can't really count on this approach, either.

Keeping track of the threads, and locking properly is certainly doable, but simply writing the files locally and having an external program do the file transfer is by far easier to write, and simpler to troubleshoot.

落墨 2024-10-25 10:42:05

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

映射驱动器后,无论线程如何,您的代码都应该使用相同的连接。我们在 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;
        }

    }

Another option could be to use a Network drive - check for the existence, and map if necessary. Code for mapping and un-mapping the drive can be found in my answer here:

Once the drive is mapped, your code should use the same connection regardless of the thread. We use this in a web service call, which is, by its very nature, multi-threaded, and it's a highly used service, copying hundreds of files per minute at peak times. I'm relatively sure it will work in your case.

C# - Map Network drive from Web Service

To check to see if the drive is already mapped, simply call

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

Edit - adding code to connect and disconnect network drives

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

    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文