【问题标题】:How to spawn worker threads and process their outputs in main thread in C#?如何在 C# 的主线程中生成工作线程并处理它们的输出?
【发布时间】:2012-11-21 02:06:58
【问题描述】:

我想在 C# 控制台应用程序中实现以下功能:

  1. 在主线程中生成多个工作线程;
  2. 每个工作线程处理数据,并定期向主线程发送字符串消息;
  3. 主线程处理消息并等待所有工作线程完成;
  4. 主线程退出。

现在我正在使用 TPL,但我不知道如何将消息从工作线程发送到主线程。谢谢你的帮助!

【问题讨论】:

    标签: c# multithreading task-parallel-library


    【解决方案1】:

    您可以将生产者/消费者模式与 TPL 一起使用,如 this example on an MSDN blog 中所示。

    或者,您可以将其踢老派并使用信号,请参阅AutoResetEvent

    或者,如果您希望在非常低级别工作,请使用Monitor.PulseMonitor.WaitOne(如here 所示)。

    无论哪种方式,您都在寻找同步,您可以在 here 上阅读。


    如果您实际上并不关心更新在哪个线程上运行,则其他选择是将委托作为参数并在那里打印更新,à la:

    static Task<string> ReadFile(string filename, Action<string> updateStatus)
    {
    
        //do stuf synchronously
        return Task<string>.Factory.StartNew(() => {
            System.Threading.Thread.Sleep(1000);
            //do async stuff
            updateStatus("update message");
            //do other stuff
            return "The result";
        });
    }
    
    public static void Main(string[] args) 
    {
        var getStringTask = ReadFile("File.txt", (update) => {
            Console.WriteLine(update)
        });
        Console.Writeline("Reading file...");
        //do other stuff here
        //getStringTask.Result will wait if not complete
        Console.WriteLine("File contents: {0}", getStringTask.Result);
    }
    

    将打印:

    Reading file...
    update message
    File contents: The result
    

    "update message"Console.WriteLine 的调用仍会在ThreadPool 线程上发生,但它仍可能满足您的需求。

    【讨论】:

      【解决方案2】:

      我会将工作线程包装到它们自己的Func 或以IEnumerable&lt;string&gt; 作为返回类型的常规方法。然后,我将为每个在 Func/ 方法上调用 foreach 的工作人员创建一个任务并处理他们的消息。

      这是一个使用两种常规方法的简单示例。如果方法是任意的,您需要创建一个List&lt;Task&gt;

      static void Main(string[] args)
      {
          var task1 = Task.Factory.StartNew(()=>{foreach (var n in Back1(13)) Console.WriteLine("From Back 1, said "+n);});
          var task2 = Task.Factory.StartNew(() => { foreach (var n in Back2(5)) Console.WriteLine("From Back 2, said " + n); });
          task1.Wait();
          task2.Wait();
          Console.WriteLine("All done");
          Console.ReadLine();
      }
      
      static IEnumerable<string> Back1(int it)
      {
          for (int i = 0; i < it; i++)
          {
              System.Threading.Thread.Sleep(100);
              yield return i +" of "+it;
          }
      
          yield return "I'm done";
      }
      
      static IEnumerable<string> Back2(int it)
      {
          for (int i = 0; i < it; i++)
          {
              System.Threading.Thread.Sleep(150);
              yield return i +" of "+it;
          }
      
          yield return "I'm done";
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-22
        • 1970-01-01
        • 2012-08-10
        • 1970-01-01
        • 1970-01-01
        • 2019-09-10
        • 2010-10-29
        • 1970-01-01
        相关资源
        最近更新 更多