Как записывать в файл из нескольких потоков?

213
04 мая 2018, 10:43

Задача: записывать в файл данные из нескольких потоков.

При последовательной записи (режим Append) работает без ошибок.

_waitWriteHandler.WaitOne();
using (BinaryWriter bw = new BinaryWriter(new FileStream(Destination, FileMode.Append, FileAccess.Write, FileShare.Write)))
{
    bw.Write(data);
}
_waitWriteHandler.Set();

А если сначала создать файл:

using (BinaryWriter bw = new BinaryWriter(new FileStream(Destination, FileMode.Create, FileAccess.Write, FileShare.None)))
{
    bw.Write(new byte[destinationFileSize]);
}

И в разные места начать писать данные:

_waitWriteHandler.WaitOne();
using (BinaryWriter bw = new BinaryWriter(new FileStream(Destination, FileMode.Open, FileAccess.Write, FileShare.None)))
{
    bw.BaseStream.Position = position;
    bw.Write(data);
}
_waitWriteHandler.Set();

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

Использую класс Thread и AutoResetEvent для синхронизации.

Answer 1

Можно получать эксклюзивные права на запись в файл(FileShare.None), как вы и делаете, но постоянные переоткрытия файла с блокировкой будут очень узким местом.
Также придётся отлавливать System.IO.IOException, например, в бесконечном цикле, чтобы дождаться освобождения файла.

Лучше всего собирать данные в разных потоках, но писать в одном, специально для этого выделенном, через механизм очереди.
Скармливаете ему "задачи", а он их выполняет. (Это называется producer-consumer)

READ ALSO
Не нажимается кнопка PhantomJS

Не нажимается кнопка PhantomJS

Пишет то , что истекло время ожидания

226
Как получить имя папки “Мой компьютер”

Как получить имя папки “Мой компьютер”

Как можно получить имя папки "Мой компьютер" для windows 10

225
Шифрование на Android и c#

Шифрование на Android и c#

есть шифрование на c# и требуется сделать аналогичное на androidПробовал по разному вот к чему пришел: на c#

212
Как можно реализовать свой ImapClient(GemBox.Email.Imap)?

Как можно реализовать свой ImapClient(GemBox.Email.Imap)?

Как можно проще реализовать ImapClient(GemBoxEmail

191