#c#
Вопрос:
существует код
- Когда chatlist.json не существует, он создается и в него помещается пустой список
- Когда chatslist.json существует, он десериализуется
private async Tasklt;ChatsInfogt; ReadChatsList() { FileInfo file = new FileInfo(chatsListPath); if (file.Exists) { using (FileStream fs = new FileStream(chatsListPath, FileMode.Open)) { ChatsInfo chatsList = await JsonSerializer.DeserializeAsynclt;ChatsInfogt;(fs); fs.Close(); return chatsList; } } else { ChatsInfo emptylist = new ChatsInfo(); emptylist.activedChats = new Listlt;longgt;(); using (FileStream fs = new FileStream(chatsListPath, FileMode.Create)) { await JsonSerializer.SerializeAsynclt;ChatsInfogt;(fs, emptylist, new JsonSerializerOptions { WriteIndented = true }); fs.Close(); } return emptylist; } private async void SerializeChatsList(ChatsInfo data) { using (FileStream fs = new FileStream(chatsListPath, FileMode.Open)) { await JsonSerializer.SerializeAsynclt;ChatsInfogt;(fs, data, new JsonSerializerOptions { WriteIndented = true }); fs.Close(); } } private async Tasklt;boolgt; ChatInTheList(long chat_id) { ChatsInfo chatsList = await ReadChatsList(); return chatsList.activedChats.Contains(chat_id); }
Есть одно условие
if(!await ChatInTheList(message.Chat.Id)) { AddChatInList(message.Chat.Id); }
Возникает ошибка, при которой появляется ошибка
System.IO.IOException: "The process cannot access the file 'C:UsersUsersourcerepostgbotbinlinux-x64netcoreapp3.1chatslist.json' because it is being used by another process." Initially, this exception was created in this call stack: [External code] tgbot.Bot.ReadChatsList() в Bot.cs [External code] tgbot.Bot.ChatInTheList(long) в Bot.cs [External code] tgbot.Bot.OnMessageReceived(object, Telegram.Bot.Args.MessageEventArgs) в Bot.cs
Почему ни одна из нитей не закрывается? Где я ошибся?
@PanagiotisKanavos
private async void AddChatInList(long chat_id) { ChatsInfo chatsList = await ReadChatsList(); chatsList.activedChats.Add(chat_id); SerializeChatsList(chatsList); }
Комментарии:
1. Не имеет отношения к вашему вопросу, но вы должны удалить все
fs.Close
.2.
async void
это ошибка. Он предназначен только для обработчиков событий. Используйтеasync Task
и ждите этого метода. В противном случае у вас нет контроля над тем, когда этот метод фактически запускается — приложение может выйти до того, как этот метод успеет завершиться3. Вполне возможно, что внешний обработчик событий (например
OnMessageReceived
) сработает во время доступа к файлу, что связано именно с тем, что вы сделали доступ к файлу асинхронным. Если бы ваш доступ к файлам был синхронным, обработчик событий не смог бы вмешаться (если только вы не работаете с потоками вручную, чего вы, похоже, не делаете).4.
Can't be awaited
это означает, что ваш код откроет поток внутриSerializeChatsList
и продолжит следующий метод , оставив поток открытым. Вы не опубликовали код, который вызываетSerializeChatsList
, поэтому можно только догадываться, что он дважды открывает один и тот же файл5. @PanagiotisKanavos До сих пор SerializeChatsList используется только в этом методе, я приведу его в вопросе для удобства чтения
Ответ №1:
Вы не ждете AddChatInList()
, поэтому, пока этот метод запущен, другой метод пытается получить доступ к файлу.
Кроме того, вы хотите разбить свой SSD-накопитель? Потому что именно так вы будете ломать свой SSD. (Нет, не совсем, эти штуки могут записывать много данных, но…) каждая строка чата приводит к операции чтения-записи всего файла, которая будет расти с каждым сообщением чата. Ваша система станет невыносимо медленной.
Комментарии:
1. Спасибо, я постараюсь свести вызов метода к минимуму
2. вот почему лучше всего называть все асинхронные методы
SomeMethodAsync
.