Я использую программу сервера сокетов, которая работает асинхронно. Мне нужно записать входящие пакеты в один файл. Одновременно подключаются сотни клиентов и могут записывать файл одновременно. Вот код, который записывает полученный пакет в файл...
static ManualResetEvent signal = new ManualResetEvent(false);
signal.WaitOne();
using (StreamWriter sw = new StreamWriter(path, true))
sw.WriteLine(message);
signal.Set();
Проблема в том, что он замедляет следующий пакет данных, который должен быть получен.
Вам нужно отделить ваше чтение и письмо. Вы можете сделать это, используя очереди.
Создайте единую поточную очередь сообщений ( ConcurrentQueue
).
Клиенты помещают сообщения в очередь.
У вас есть один писатель, который выдает сообщения из очереди и каждый раз связывает каждое сообщение с диском (одновременный файл IO из нескольких потоков обычно является убийцей производительности).
Теперь единственная синхронизация, в которой вы нуждаетесь, заботится о очереди, поэтому она прекрасно устраняет потенциальный источник блокировки/блокировки, и оба конца цепи потребителей/производителей могут работать на максимальной скорости.
Кроме того, взгляните на TPL DataFlow. Он создан для таких видов производства/потребления. Это достойное вложение вашего времени.
ConcurrentQueue
- хороший вариант, так как он может брать элементы из очереди, не затрагивая свои входящие данные, кроме необходимости синхронизировать их, поскольку ConcurrentQueue
- это FIFO.
Не понятно, как вы получаете данные. Если вы сделаете так, как мне кажется, выполните асинхронную прогонную операцию ведения журнала (исправление кода):
// 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);
}
});