【问题标题】:Strange behavior of Multiple Processes多进程的奇怪行为
【发布时间】:2011-01-21 08:05:43
【问题描述】:

我写了两个 Windows 控制台应用程序如下

class ProgramA
{
    static void Main(string[] args)
    {

        FileStream fs = File.Open(@"E:\console.txt", FileMode.OpenOrCreate);
        StreamWriter sw = new StreamWriter(fs);
        TextWriter old = Console.Out;
        Console.SetOut(sw);
        Console.WriteLine("Process A Started " + DateTime.Now.ToString());
        sw.Flush();
        Process p = new Process();
        ProcessStartInfo pi = new ProcessStartInfo();
        pi.FileName = @"D:\ProgramB.exe";
        p.StartInfo = pi;
        pi.UseShellExecute = true;
        pi.RedirectStandardOutput = false;
        bool result = p.Start();

        Console.WriteLine("Process A Ended " + DateTime.Now.ToString());
        sw.Flush();
    }
}

class ProgramB
{
    static void Main(string[] args)
    {
        try
        {
            FileStream fs = File.Open(@"E:\console.txt", FileMode.OpenOrCreate);
            StreamWriter sw = new StreamWriter(fs);
            TextWriter old = Console.Out;
            Console.SetOut(sw);
            Console.WriteLine("Process B output " + DateTime.Now.ToString());
            sw.Flush();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

它们是完全不同的 exe 文件。当我用 F5 一步步调试 ProgramA 时,E:\console.txt 中的结果是

流程 A 开始于 2/26/2010 13:43:59 过程 A 结束于 2/26/2010 13:44:03

但是如果我只是用 Ctrl+F5 运行 ProgramA,E:\console.txt 中的结果是

过程 B 输出 2/26/2010 13:48:50 过程 A 结束于 2/26/2010 13:48:50

我很困惑。最初,我想让 2 个进程都写入同一个文件。但是经过一番思考,我想既然进程A首先控制了console.txt,那么进程B应该无法访问console.txt,结果应该类似于下图:

流程 A 开始于 2/26/2010 13:43:59 过程 A 结束于 2/26/2010 13:44:03

进程 B 抛出拒绝访问异常。但事实并非如此。为什么? “进程 A 已启动”消息在哪里?


我将代码更改为以下内容:

class ProgramA
{
    static void Main(string[] args)
    {

        FileStream fs = File.Open(@"E:\console.txt", FileMode.OpenOrCreate);
        StreamWriter sw = new StreamWriter(fs);
        TextWriter old = Console.Out;
        Console.SetOut(sw);
        Console.Write("aaaaa");
        Console.Write("AAAAA");
        sw.Flush();
        Process p = new Process();
        ProcessStartInfo pi = new ProcessStartInfo();
        pi.FileName = @"D:\ProgramB.exe";
        p.StartInfo = pi;
        pi.UseShellExecute = true;
        pi.RedirectStandardOutput = false;
        bool result = p.Start();
        Console.Write("aaaaa");
        sw.Flush();
    }

class ProgramB
{
    static void Main(string[] args)
    {
        try
        {
            FileStream fs = File.Open(@"E:\console.txt", FileMode.OpenOrCreate);
            StreamWriter sw = new StreamWriter(fs);
            TextWriter old = Console.Out;
            Console.SetOut(sw);
            Console.Write("bbb");
            sw.Flush();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

console.txt的内容是

bbbaaAAAAAAaaaaa

也许这可以解释一些事情。我在想办法。

谢谢。

【问题讨论】:

    标签: c# operating-system


    【解决方案1】:

    两件事:

    • 首先,由于您没有使用过 FileShare.None,所以两个 exe 都可以访问该文件,因此进程 B 仍然可以访问该文件。

    • 其次,由于您已使用 OpenOrCreate(仅此而已)打开文件,因此将打开该文件,并且您所做的写入将从文件的 start 开始。在写入之前尝试执行 FileStream.Seek 以查找文件末尾。我认为在 FileMode.Append 中打开文件并没有真正的帮助(如果你并行运行它们),因为这两个进程仍然会互相践踏。

    更好的是,尝试执行 FileStream.Lock 以确保两个进程不会相互践踏。

    【讨论】:

    • 我添加了 FileShare.None 但进程 B 仍然可以访问该文件。但是,如果我在程序 A 运行时独立运行程序 B,则会引发拒绝访问异常。如果我让进程 B 由进程 A 启动,则没有例外,进程 B 仍然可以写入文件。是不是因为进程B是A启动的,继承了A的文件?
    • 您可能甚至在 B 打开文件之前就退出了进程 A(因此 B 可以打开)。尝试在启动 B 后将 Console.Read 或其他内容放入进程 A 中,看看会发生什么。
    【解决方案2】:

    尝试在File.Open 方法中使用FileMode.OpenOrCreate | FileMode.Append

    【讨论】:

      猜你喜欢
      • 2021-07-03
      • 1970-01-01
      • 1970-01-01
      • 2013-03-15
      • 2015-01-07
      • 2017-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多