C# 如何保证在多线程处理中写入文件而不发生异常?

C# 如何保证在多线程处理中写入文件而不发生异常?,c#,multithreading,exception,streamwriter,C#,Multithreading,Exception,Streamwriter,这是一个简化的例子 namespace ConsoleApplication1 { class Program { static void Main(string[] args) { new Thread(() => Method1()).Start(); new Thread(() => Method2()).Start(); Console.Read();

这是一个简化的例子

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=newfilestream(@“h:\data.txt”,FileMode.Create)

    使用(StreamWriter sw=新StreamWriter(fs,Encoding.Default,10))

  • 不起作用,因为只有当大约385个整数在缓冲区中等待写入文件时,才会发生第一次写入操作

  • 如果我在异常发生之前关闭写入程序,文件将被填充。但这不是一个好的选择——我必须每秒写入文件1到10次。如此频繁地打开和关闭作者不是一个好主意,是吗

  • 我可以捕捉到这样的异常

    私有静态void方法2() {

    }

  • 一切都会好的-没有申请终止和文件将填写一包一包。但事实并非如此——我无法控制何时何地发生异常。我尝试在任何地方使用try-catch,但我可能会错过一些东西


    因此,情况是:StreamWriter的缓冲区未满,异常发生在另一个线程中并且未被捕获,因此应用程序将被终止。如何不丢失这些数据并将其写入文件?

    据我所知,您假设某个地方存在错误,该过程可能随时终止。您希望保存尽可能多的数据

    您应该能够在
    StreamWriter
    上调用
    Flush
    。这将把数据推送到操作系统。如果进程终止,数据最终将由操作系统写入

    如果由于某种原因,您无法说服
    StreamWriter
    实际刷新,您可以使用
    FileStream
    并对其进行写入(伪代码:
    FileStream.write(Encoding.GetBytes(myString))
    )。然后,您可以刷新
    文件流
    ,或使用1的缓冲区大小

    当然,如果您首先阻止进程被终止,这是最好的。与使用原始
    线程相比,
    任务通常是直接执行的。

    流将确保其所有内容都被推送到其底层文件中


    这将确保在您完成操作后保存所有数据,并且以下异常不会使您的应用程序丢失数据。

    您是否尝试
    刷新流而不是关闭流。这应该注意将数据保存到文件中,同时让流打开并接受进一步的数据。也就是说,我建议您检查关键字和存在的对象,以解决这些并发性问题。如果您只需在
    try{}catch{finally}中包装Main方法,您就可以捕获程序中的任何异常
    block并在
    finally
    block中等待工作线程完成执行所以谷歌“关键部分”。@Sidewinder94 Flush()和AutoFlush是一个解决方案。我试过了,效果很好。非常感谢。如果你把你的评论作为回答,我会接受。谢谢你的回答。我认为它是有用的,但认为@Sidewinder94的答案是被接受的,因为他是第一个。我也会考虑使用任务而不是线程,但是现在实际应用程序使用线程,所以我需要一个快速的线程解决方案。
    try
    {
        Thread.Sleep(6000);
        throw null;
    }
    catch
    {
        Console.WriteLine("Exception!");
    }