基于任务的异步模式的“Hello World”?

时间:2012-11-27 20:00:58

标签: .net multithreading task-parallel-library

由于基于任务的异步模式现在是推荐的路由(每个MSDN @ herehere),我如何将下面的简单hello world代码转换为任务 - 基于异步模式?

让我们假设我对Tasks一无所知,我试图向工作人员演示输入和输出,以及从'main'调用。

class Program
{
    static void Main(string[] args)
    {
        Worker wk = new Worker();
        string result = wk.DoWork(1000);
        Console.WriteLine(result);
        Console.WriteLine("Main says, Hello World!");
        Console.ReadLine();
    }

}
class Worker
{
    public string DoWork(int delay)
    {
        Console.WriteLine("Worker says, working ...");
        Thread.Sleep(delay); // represents the 100ms+ workload            
        return "Worker says, I'm done! Hello World!";
    }
}

2 个答案:

答案 0 :(得分:3)

这取决于你想要做什么异步。如果Thread.Sleep()代表一些受CPU限制的工作,那么使用TAP就不会有太大的收获。

如果您想让DoWork()内的等待异步,则意味着将签名从string更改为async Task<string>,然后使用await Task.Delay()代替Thread.Sleep()

如果您还想使Main()异步,则会更复杂,因为Main()实际上不能async。相反,您可以为真实MainAsync()中的异步Wait()创建异步Main(),然后同步await。这意味着主线程将被阻止,但我们需要保持应用程序活着。此外,将异步Wait()与同步Main()混合通常不是一个好主意(特别是因为它经常导致死锁),但在这种情况下它没关系。

如果我们使ReadLine()异步,那么阻塞Console.ReadLineAsync()也是异步的。没有Console.In,但我们可以使用class Program { static void Main() { MainAsync().Wait(); } static async Task MainAsync() { var worker = new Worker(); string result = await worker.DoWork(1000); Console.WriteLine(result); Console.WriteLine("Main says, Hello World!"); await Console.In.ReadLineAsync(); } } class Worker { public async Task<string> DoWork(int delay) { Console.WriteLine("Worker says, working ..."); await Task.Delay(delay); // represents the 100ms+ workload return "Worker says, I'm done! Hello World!"; } }

所以,最终的代码看起来像这样:

{{1}}

答案 1 :(得分:2)

我知道你想在一个单独的线程上执行DoWork()并返回结果。虽然没有意义,因为线程在这个例子中不会实现任何东西,但下面是代码。

class Program
{
    static void Main(string[] args)
    {
        Worker wk = new Worker();
        Task<string> task = Task.Factory.StartNew(() => wk.DoWork(1000));
        Console.WriteLine(task.Result);
        Console.WriteLine("Main says, Hello World!");
        Console.ReadLine();
    }

}

Task.Factory.StartNew()接受委托并立即开始在单独的线程上执行它。它返回一个表示操作的Task对象。 <{1}}将阻止当前线程,直到task.Result返回。