Общая папка слишком много подключений проблема в C # - PullRequest
1 голос
/ 21 февраля 2011

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

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

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

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

Ответы [ 6 ]

3 голосов
/ 21 февраля 2011

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

Вы можете:

  • Использовать менее 20 подключений
  • Использоватьдругой протокол копирования файлов, хотя вы затем столкнетесь с ограничением на количество сетевых сокетов
  • Переключитесь на серверную ОС, где такого ограничения нет
2 голосов
/ 21 февраля 2011

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

1 голос
/ 21 февраля 2011

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

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

0 голосов
/ 21 февраля 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;
        }

    }
0 голосов
/ 21 февраля 2011

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

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

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

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

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

0 голосов
/ 21 февраля 2011

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

...