c#-复制控制台类行为中的多线程

c#-复制控制台类行为中的多线程,c#,multithreading,C#,Multithreading,我有一个按顺序执行4个函数的应用程序。在每个函数中,我都有使用console.writeline记录的输出。控制台内部用于将所有数据重定向到文件 我必须改变工作方式,以便所有四个功能可以并行运行。其他一切正常我关心的是文件中的输出日志记录console.writeline现在将以我不希望的随机顺序在文件中写入数据。我希望所有线程都完成,然后按照我希望的顺序记录所有数据的输出 那么如何在每个线程内捕获输出呢 在一个字符串中,然后对我生成的所有4个字符串执行console.writeline? 为每

我有一个按顺序执行4个函数的应用程序。在每个函数中,我都有使用
console.writeline
记录的输出。控制台内部用于将所有数据重定向到文件

我必须改变工作方式,以便所有四个功能可以并行运行。其他一切正常我关心的是文件中的输出日志记录
console.writeline现在将以我不希望的随机顺序在文件中写入数据。我希望所有线程都完成,然后按照我希望的顺序记录所有数据的输出

那么如何在每个线程内捕获输出呢

  • 在一个字符串中,然后对我生成的所有4个字符串执行
    console.writeline
  • 为每个线程捕获文件中的数据,并在所有线程完成时执行
    控制台。writeline
  • 其他一些类,如
    Console
    ,其中数据的读取/写入方式与
    Console
    类相同

  • 我基本上希望输出与应用程序按顺序运行所有函数时的输出完全相同

    据我所知,这四个方法总是一起调用的,所以每次调用它们时,您可以做的是,首先在日志文件中附加四行空行,然后每个方法都可以将自己的输出写在与日志文件中的行数相对应的预定行上。若您绝对不想等待所有方法完成,那个么您就可以这样做

    但是,由于访问文件比在字符串中写入值要长,我建议您使用字符串数组或类似的东西:

    string[] output = new string[4];
    private void method1()
    {
        output[1] = some_stuff.ToString();
    }
    ...
    
    当所有线程都结束时,您可以一次写入所有线程

    foreach (string s in output) Console.WriteLine(s);
    

    这几乎是最简单、最快捷的方法。

    您应该看看任务并行库(Task Parallel Library,TPL)

    然后,您可以启动多个任务,等待所有任务完成,然后按您喜欢的顺序打印它们的结果(例如字符串)

    这来自msdn文档():

    等待所有任务完成:

    // Wait for all tasks to complete.
    Task[] tasks = new Task[10];
    for (int i = 0; i < 10; i++)
    {
       tasks[i] = Task.Factory.StartNew(() => DoSomeWork(10000000));
    }
    Task.WaitAll(tasks);
    
    //等待所有任务完成。
    任务[]任务=新任务[10];
    对于(int i=0;i<10;i++)
    {
    tasks[i]=Task.Factory.StartNew(()=>DoSomeWork(10000000));
    }
    Task.WaitAll(任务);
    
    具有返回值的任务:

    // Return a value type with a lambda expression
    Task<string> task1 = Task<string>.Factory.StartNew(() => "some text");
    int i = task1.Result;
    
    //返回带有lambda表达式的值类型
    task1=Task.Factory.StartNew(()=>“一些文本”);
    int i=任务1.结果;
    
    如果您知道所有输出都可以放入内存,那么您可以将输出写入字符串,然后在完成后将这些字符串附加到文件中

    有许多方法可以输出到字符串。出于您的目的,可能最简单的方法是为每个线程创建一个。例如:

    StringWriter output = new StringWriter();
    
    然后,替换对
    输出.WriteLine
    的所有
    控制台.WriteLine
    调用

    线程完成后,它可以通过调用
    ToString
    将输出转换为字符串。即:

    string threadOutput = output.ToString();
    
    然后获取每个线程的输出,并按照您想要的顺序写入文件

    如果输出太大,无法放入内存,则让每个线程打开一个线程,该线程将写入文件。完成四个线程后,您可以依次打开每个文件、读取数据和写入输出。比如:

    using (FileStream outputFile = File.OpenWrite(outputFileName))
    {
        // do the following for each thread's output
        using (FileStream threadFile = File.OpenRead(inputFilename))
        {
            threadFile.CopyTo(outputFile);
        }
    }
    

    好啊如果日志消息的数量不是很大,我会使用字符串,否则我会使用文件。然后实现一个自己的类来处理线程等待完成等,就像在TPL中一样。如果每个线程输出已知数量的行,那么这个类就可以正常工作。尽管在不影响第1行或第3行的情况下覆盖文本文件中的第2行可能会有问题。无论如何,如果线程的输出事先未知,此解决方案将无法工作。您不能将所有需要的行写入一个以“\n”分隔的字符串中吗?或者简单地使用一个二维数组。当然,您可以构造一个包含换行符的字符串。基本上,您需要为每个线程创建一个
    StringBuilder
    ,并调用
    AppendLine
    添加一行。在这种情况下,不需要数组。使用二维数组是有问题的,因为不能有效地调整数组的大小。顺便说一下,我不是那个否决你答案的人。