Как можно обеспечить удаление FileStream после того, как все записи WriteAsync() в текущем файле завершены?

83
12

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

Я прочитал документацию FileStream и предложил использовать FileStream.WriteAsync() для лучшей производительности.

public void WriteData(byte[] data)
{
counter++;
if (counter == 1000)
{
counter = 0;

// Close the current filestream and open a new one.
filestream.Dispose();
filestream = new FileStream(this.outputPath, FileMode.Create,
FileAccess.Write, FileShare.None, 4096, true);
}

filestream.WriteAsync(data, 0, data.Length);
}

Однако в вышеприведенной функции моя гипотеза заключается в том, что все WriteAsync() не выполняются до того, как я вызову filestream.Dispose(). Есть ли способ убедиться, что я только Dispose() после того, как все мои WriteAsync() завершены? Обратите внимание, что делегат этого события вызывается последовательно 1000 - 2000 раз в секунду, а WriteAsync копирует 240 КБ на звонок на SSD.

Одно из решений, о котором я могу думать, - это немедленно немедленно избавиться от каждого Filestream, я могу сохранить его в массиве Filestream а затем избавиться от них, как только Filestream весь процесс записи данных, и больше никаких событий не начнется. Будет ли это работать? Даже тогда, как я могу "дождаться" до тех пор, пока все WriteAsync() не будут завершены?

спросил(а) 2016-11-30T20:54:00+03:00 3 года, 11 месяцев назад
1
Решение
90

Не отвечая на точный вопрос, основываясь на последующих комментариях, я предлагаю вам сделать следующее:

    Создайте ConcurrentQueue во всех событиях, связанных с событиями На каждое событие добавьте в эту очередь Создайте отдельный поток, который обслуживает очередь, удаляет события и записывает их на диск. Затем вы можете точно определить, как часто вы хотите открывать, писать, переименовывать и т.д., И у вас нет проблем параллелизма потоков в активности файлов, с которыми приходится иметь дело. В зависимости от вашего требования, в вашем потоке писателя вы можете просто опросить очередь каждую секунду или около того, или у вас может быть более сложный подход с использованием WaitHandle чтобы сигнализировать, когда данные готовы к записи, когда очередь пуста, когда она получила N элементов в нем и т.д. Поскольку вы так часто накапливаете данные, возможно, опрос прекрасен, так как вы почти всегда найдете данные для записи. Очевидно, что вам необходимо полностью закрыть закрытие приложения - например, прекратить запись из событий, одиночную запись в потоке записи, чтобы остановить ее, очистить последние элементы до диска, дождаться ее остановки.

Это больше работает, но вы получаете:

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

Есть, вероятно, готовые решения для этого (использование буферизованного log4net Appender приходит на ум); это если вы хотите бросить свои собственные.

Вы можете сделать это с помощью "стандартной" потоковой передачи (т.е. Thread), или вы можете просто создать свой поток писем как Task.

ответил(а) 2016-11-30T22:40:00+03:00 3 года, 11 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема