Общая папка слишком много подключений проблема в с #

Я пытаюсь скопировать несколько файлов в общую папку (около 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 equipo remoto en este momento, ya que hay más de las que puede aceptar"

Переведено было бы что-то вроде

«В настоящее время к этому удаленному компьютеру нельзя подключиться, так как он может принимать другие подключения»

Есть ли другой способ скопировать файл в общую папку или явно закрыть соединение?


person DkAngelito    schedule 21.02.2011    source источник


Ответы (6)


Рабочие станции Windows имеют ограничение на количество сетевых подключений, которые они могут принимать одновременно.

Вы могли:

  • Используйте менее 20 подключений
  • Используйте другой протокол копирования файлов, хотя в этом случае вы столкнетесь с ограничением количества сетевых сокетов.
  • Переключитесь на использование серверной ОС, где такого ограничения нет
person Tim Robinson    schedule 21.02.2011

Попробуйте скопировать файлы в одном потоке. Я уверен, что наличие одного потока на соединение позволяет серверу достичь своего предела.

person Daniel A. White    schedule 21.02.2011

Клиентские операционные системы Windows ограничены количеством одновременных подключений, которые они могут принять. Даже если это серверная система, общий доступ к файлам Windows также позволяет администратору ограничивать количество подключений к общему ресурсу.

Что вы, вероятно, захотите сделать, так это ограничиться несколькими одновременными потоками (от 3 до 5 должны делать это). Поместите все имена файлов в очередь и пусть каждый поток выводит из очереди (с соответствующей блокировкой) следующий файл для обработки, пока очередь не станет пустой. Это называется схемой производитель / потребитель. В качестве бонуса вы, скорее всего, в любом случае получите большую пропускную способность, чем выполнение всех 20 сразу, потому что системе нужно тратить меньше времени на беспокойство о сетевых конфликтах и ​​переключениях контекста.

person Joel Coehoorn    schedule 21.02.2011

Помните, что скорость ввода-вывода почти всегда является узким местом, поэтому вам может быть лучше ограничить передачу одним или двумя файлами за раз. Вы, вероятно, ограничиваете либо чтение с диска, либо пропускную способность сети. Лучше всего измерить производительность, начиная с 1 потока, и найти баланс скорости передачи и потоков.

person ChaosPandion    schedule 21.02.2011

Проблема в том, что каждый поток устанавливает собственное соединение. Если у вас запущено больше потоков, которые не может принять целевая машина, вы столкнетесь с этой проблемой. Вам нужно найти способ гарантировать, что вы не превысите этот лимит.

Есть ли причина, по которой это должно быть многопоточным? Я уверен, что ответ - «да», но на тот случай, если вы думаете, что многопоточность ускоряет операции копирования, позволяя выполнять несколько операций копирования одновременно, это не так. Bamdwidth ограничена, и целевой компьютер сможет читать / писать только с определенной скоростью, поэтому, пытаясь записать несколько файлов в нескольких потоках, вы фактически просто замедляете каждый файл по отдельности.

Однако, если я догадываюсь правильно и есть еще одна причина для нескольких потоков, позвольте мне предложить альтернативу: записать файлы локально и скопировать файлы с помощью совершенно другого процесса. У вас есть служба Windows или консольное приложение, которое может копировать файлы, в то время как поток пользовательского интерфейса и другие потоки выполняют свою работу. Добавление посредника может добавить немного дополнительной сложности, но это все же проще, чем пытаться найти способ решить эту проблему.

Альтернативой может быть отслеживание потоков и обеспечение того, чтобы количество потоков никогда не превышало количество подключений, доступных на целевой машине, И вам нужно беспокоиться о других процессах, подключающихся к машине, поэтому вы не можете действительно подсчитать на этом подходе тоже.

Отслеживание потоков и правильная блокировка, безусловно, выполнимы, но просто записать файлы локально и выполнить передачу файлов с помощью внешней программы, намного проще написать и проще устранить неполадки.

person David    schedule 21.02.2011

Другой вариант может заключаться в использовании сетевого диска - проверьте наличие и сопоставьте, если необходимо. Код для сопоставления и отмены сопоставления диска можно найти в моем ответе здесь:

После сопоставления диска ваш код должен использовать одно и то же соединение независимо от потока. Мы используем это в вызове веб-службы, которая по самой своей природе является многопоточной и широко используемой службой, копирующей сотни файлов в минуту в часы пик. Я почти уверен, что в вашем случае это сработает.

C # - отображение сетевого диска из веб-службы

Чтобы проверить, назначен ли уже диск, просто позвоните

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

    }
person David    schedule 21.02.2011