Чтение и запись в файл с помощью BlockingCollection

109
16 апреля 2021, 07:50

Доброго времени суток!

У меня есть класс который производит чтение и запись в файл, но периодически появляется исключение о том что данный файл занят другим потоком.

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

Буду очень благодарен за помощь в решении данной задачи!

Для полного представления приведу 2 примера кода:

Первый нужно переделать с использованием BlockingCollection

static class Setting
    {
        private static string FileDirectory = Assembly.GetExecutingAssembly().Location;
        private static string FileCatalog = "bin/account/";
        private static string FileName = "setting.elum";

        public static async Task<bool> Write()
        {
            try
            {
                if (!Directory.Exists((FileDirectory.Remove(FileDirectory.Length - Assembly.GetExecutingAssembly().FullName.Length)) + FileCatalog))
                {
                    CreateDirectory(FileCatalog);
                }
                string json = JsonConvert.SerializeObject(Global.globalBinding);
                if(json != null)
                {
                    await Task.Factory.StartNew(() => File.WriteAllText(FileCatalog + FileName, json, Encoding.UTF8));
                    return true;
                }
                return false;
            }
            catch (Exception ex) { return false; }
        }

        public static async Task<bool> Read()
        {
            string dir = FileCatalog + FileName;
            try
            {
                if (!System.IO.File.Exists(dir))
                {
                    await Write();
                }
                using (var reader = File.OpenText(dir))
                {
                    var json = await reader.ReadToEndAsync();
                    if (json != "")
                    {
                        var a = JsonConvert.DeserializeObject<GlobalBinding>(json);
                        Global.globalBinding = a;
                        if(Global.globalBinding == a)
                        {
                            return true;
                        }
                    }
                    else
                    {
                        var a = await Write();
                        if(a != false)
                        {
                            return true;
                        }
                        else
                        {
                            return false;
                        }
                    }
                }
                return true;
            }
            catch { return false; }
        }
        private static void CreateDirectory(string pach)
        {
            Directory.CreateDirectory(pach);
        }

    }

А второй работает но только на запись

    internal static class log
    {
        private static string _fileDirectory = Assembly.GetExecutingAssembly().Location;
        private static string _fileCatalog = "bin/logout/";
        private static string _fileName = "log.elum";
        private static BlockingCollection<string> _blockingCollection;
        private static Task _task;
        static log()
        {
            _fileDirectory = _fileDirectory.Remove(_fileDirectory.Length - 8) + _fileCatalog;
            _blockingCollection = new BlockingCollection<string>();
            // Проверка существования директории
            if (!Directory.Exists(_fileDirectory))
            {
                CreateDirectory(_fileDirectory);
            }
            // Задача для записи  в файл
            _task = Task.Factory.StartNew(() =>
            {
                using (var streamWriter = new StreamWriter(_fileDirectory + _fileName, true, Encoding.UTF8))
                {
                    streamWriter.AutoFlush = true;
                    foreach (var s in _blockingCollection.GetConsumingEnumerable())
                        streamWriter.WriteLine(s);
                }
            },
            TaskCreationOptions.LongRunning);
        }
        // Добавление в очередь на запись в файл
        public static void WriteLog(string action, string errorDiscription, int errorCode = 0)
        {
            _blockingCollection.Add($"{DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff")} действие: {action}, код: {errorCode.ToString()}, описание: { errorDiscription} ");
        }
        //Создание отсутствующей директории
        private static void CreateDirectory(string pach)
        {
            DirectoryInfo di = Directory.CreateDirectory(pach);
        }
        // выключение записи из очереди
        public static void Flush()
        {
            _blockingCollection.CompleteAdding();
            _task.Wait();
        }
    }
READ ALSO
Как организовать взаимодействие с++ кода и с# формы?

Как организовать взаимодействие с++ кода и с# формы?

Моей задачей было написание математической модели на С++, которая моделирует работу гидравлической системы, что я и сделалДля удобства тестирования...

106
Создание файла gitignore [дубликат]

Создание файла gitignore [дубликат]

Создаю один маленький проект, который необходимо залить на BitbucketПроект - Классическое приложение Window - WPF,

80
Как использовать прокси в TLSharp?

Как использовать прокси в TLSharp?

Вот мой основной кодИспользую последнюю версию TLSharp для авторизации в Telegram

113
Как преобразовать строку в массив uint с основанием 2^32

Как преобразовать строку в массив uint с основанием 2^32

Подскажите пожалуйста как из например "12413523578274952895672975235" сделать массив uint[] digits в котором будут храниться коэффициенты разложения этого длинного...

111