Если Вы связываетесь с IEnumerable. Необходимо ли быть в цикле foreach? Если не Вы могли бы объявить переменную незадолго до цикла foreach. Установите его во время цикла. Затем используйте его после цикла (если не пустой)
Одна из распространенных ошибок при использовании потоков - копирование байтов за раз или использование небольшого буфера. Большая часть времени, необходимого для записи данных на диск, тратится на поиск, поэтому использование большего буфера уменьшит среднее время поиска на байт.
Операционные системы записывают файлы на диск в кластерах. Это означает, что когда вы записываете один байт на диск, Windows фактически записывает блок размером от 512 до 64 КБ. Вы можете значительно повысить производительность диска, используя буфер, который является целым числом, кратным 64 КБ.
Кроме того, вы можете получить повышение за счет использования буфера, который кратен размеру страницы базовой памяти вашего процессора. Для машин x86 / x64 это может быть установлено как 4 КБ, так и 4 МБ.
Итак, вы хотите использовать целое число, кратное 4 МБ.
Кроме того, если вы используете асинхронный ввод-вывод, вы можете полностью использовать преимущества большого размера буфера.
class Downloader
{
const int size = 4096 * 1024;
ManualResetEvent done = new ManualResetEvent(false);
Socket socket;
Stream stream;
void InternalWrite(IAsyncResult ar)
{
var read = socket.EndReceive(ar);
if (read == size)
InternalRead();
stream.Write((byte[])ar.AsyncState, 0, read);
if (read != size)
done.Set();
}
void InternalRead()
{
var buffer = new byte[size];
socket.BeginReceive(buffer, 0, size, System.Net.Sockets.SocketFlags.None, InternalWrite, buffer);
}
public bool Save(Socket socket, Stream stream)
{
this.socket = socket;
this.stream = stream;
InternalRead();
return done.WaitOne();
}
}
bool Save(System.Net.Sockets.Socket socket, string filename)
{
using (var stream = File.OpenWrite(filename))
{
var downloader = new Downloader();
return downloader.Save(socket, stream);
}
}
Возможно, ваше приложение может выполнять многопоточность для получения файла с помощью несколько потоков, однако пропускная способность ограничена скоростью устройств, передающих контент
Самый простой способ - открыть файл в необработанном / двоичном режиме (то есть C говорит не уверен, что эквивалент C #) и читать и записывать очень большие блоки (несколько МБ) за раз.
Уловка, которую использует TeraCopy, заключается в том, чтобы сделать чтение и запись асинхронными. Это означает, что один блок данных может быть записан, в то время как другой читается.
Вы должны возиться с количеством блоков и размером этих блоков, чтобы получить оптимальный для вашей ситуации.
Если вы запустите Process Monitor , вы сможете увидеть размеры блоков, которые использует Windows Explorer или TeraCopy.
В Vista размер блока по умолчанию для локальной сети составляет примерно 2 МБ, что значительно ускоряет копирование файлов по огромному каналу.
Зачем изобретать велосипед?
Если ваша ситуация позволяет, вам, вероятно, лучше обратиться к одной из существующих утилит «быстрого» копирования, чем пытаться написать ее самостоятельно. Существует множество неочевидных крайних случаев, с которыми необходимо справиться, и для достижения стабильно хорошей производительности требуется много экспериментов методом проб и ошибок.