Где я не закрыл ручей?

#c#

Вопрос:

существует код

  1. Когда chatlist.json не существует, он создается и в него помещается пустой список
  2. Когда 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 .