Это упрощенный примерКак гарантировать запись в файл в многопоточности с исключениями?
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
new Thread(() => Method1()).Start();
new Thread(() => Method2()).Start();
Console.Read();
}
private static void Method1()
{
using (StreamWriter sw = new StreamWriter(@"h:\data.txt"))
{
int i = 100000000;
while (true)
{
Thread.Sleep(100);
sw.WriteLine(i);
i++;
}
}
}
private static void Method2()
{
Thread.Sleep(6000);
throw null;
}
}
}
StreamWriter не записывает данные в файл, если исключение происходит слишком рано, и в другом потоке. Файл data.txt пуст во время возникновения исключения.
Я играл с этой ситуацией немного и нашел кучу обходных путей:
Если я увеличить интервал ожидания для нити, за исключением (и уменьшить интервал между сочинениями в файл) файл будет заполнен данные. Это не выбор, потому что я не знаю, когда возникает исключение.
Как следствие предыдущего обходного пути я могу уменьшить размер буфера записи потока. Но, похоже, он не работает, если я его слишком мал - например, этот код
FileStream fs = new FileStream (@ "h: \ data.txt", FileMode.Create);
используя (StreamWriter SW = новый StreamWriter (фс, Encoding.Default, 10))
не работает, потому что первая операция записи происходит только тогда, когда около 385 целых чисел ожидания в буфере будет записанный в файл.
Файл будет заполнен, если я закрою запись перед исключением. Но это не очень хороший выбор - я должен писать в файл от 1 до 10 раз в секунду. Не так хорошо открывать и закрывать писателя так часто, не так ли?
Я не могу поймать исключение как этот
частной статической ничтожной method2() {
try { Thread.Sleep(6000); throw null; } catch { Console.WriteLine("Exception!"); }
}
и все будет в порядке - не завершение работы приложения и файл будут заполнены пакетом. Но это тоже не так - я не могу контролировать, когда и где происходят исключения. Я пытаюсь использовать try-catch повсюду, но могу что-то пропустить.
Итак, ситуация: буфер буфера StreamWriter не заполнен, исключение произошло в другом потоке и не уловлено, поэтому приложение будет прекращено. Как не потерять эти данные и записать их в файл?
Вы пытались «Слить» поток, а не закрывать его. Это должно заботиться о сохранении данных в файле, позволяя потоку открывать и принимать дополнительные данные. – Sidewinder94
При этом я бы рекомендовал вам проверить ['lock'] (https://msdn.microsoft.com/en- us/library/c5kehkcz.aspx) и объект ['Mutex'] (https://msdn.microsoft.com/en-us/library/system.threading.mutex (v = vs.110) .aspx), который существует, чтобы решить эти проблемы параллелизма. – Sidewinder94
Вы можете поймать любое исключение в программе, если вы просто перенесите Main method в 'try {} catch {} finally {}' block и в 'finally' block дождитесь окончания работы Thread для завершения выполнения – Fabjan