Запись в тот же файл одновременно задерживает

1

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

static ManualResetEvent signal = new ManualResetEvent(false);
signal.WaitOne();
using (StreamWriter sw = new StreamWriter(path, true))
       sw.WriteLine(message);
signal.Set();

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

  • 0
    открытие и закрытие потока будет немного больно, разве вы не можете оставить его открытым и добавить к нему?
  • 0
    Есть ли способ обновить файл мгновенно?
Показать ещё 1 комментарий
Теги:
file

2 ответа

4
Лучший ответ

Вам нужно отделить ваше чтение и письмо. Вы можете сделать это, используя очереди.

Создайте единую поточную очередь сообщений ( ConcurrentQueue).

Клиенты помещают сообщения в очередь.

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

Теперь единственная синхронизация, в которой вы нуждаетесь, заботится о очереди, поэтому она прекрасно устраняет потенциальный источник блокировки/блокировки, и оба конца цепи потребителей/производителей могут работать на максимальной скорости.

Кроме того, взгляните на TPL DataFlow. Он создан для таких видов производства/потребления. Это достойное вложение вашего времени.

  • 0
    +1 ConcurrentQueue - хороший вариант, так как он может брать элементы из очереди, не затрагивая свои входящие данные, кроме необходимости синхронизировать их, поскольку ConcurrentQueue - это FIFO.
  • 0
    Спасибо за ответ. Я попробую ConncurrentQueue для быстрого решения и исследую TPL DataFlow для лучшего решения.
0

Не понятно, как вы получаете данные. Если вы сделаете так, как мне кажется, выполните асинхронную прогонную операцию ведения журнала (исправление кода):

// define this somewhere to lock access to "path" file
private readonly object _lock = new object();

Task.Run(() =>
    {
        lock(_lock)
        {
            using (StreamWriter sw = new StreamWriter(path, true))
                sw.WriteLine(message);
        }
    });

Ещё вопросы

Сообщество Overcoder
Наверх
Меню