4

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

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

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

4

2 回答 2

4

您可以将生产者/消费者模式与 TPL 一起使用,如MSDN 博客上的此示例所示

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

或者,如果您希望在非常低的级别上工作,请使用Monitor.Pulsewith Monitor.WaitOne(如此处所示

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


其他选项,如果您实际上并不关心更新在哪个线程上运行,则将委托作为参数并在那里打印更新,à 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但它仍可能满足您的需求。

于 2012-11-21T02:37:07.913 回答
1

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

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

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";
}
于 2012-11-21T02:35:51.833 回答