6

タスクベースの非同期パターンが推奨されるルートになっているため(MSDN @ hereおよびhereにhello worldよる)、以下の単純なコードをタスクベースの非同期パターンに変換するにはどうすればよいですか?

私は何も知らずTasks、ワーカーへの入力とワーカーからの出力、および「メイン」からの呼び出しをデモしようとしたと仮定します。

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!";
    }
}
4

2 に答える 2

4

これは、正確に何を非同期にしたいかによって異なります。がCPUにバインドされた作業を表す場合、Thread.Sleep()TAPを使用してもあまりメリットはありません。

内部で待機を非同期にしたい場合はDoWork()、署名をからstringに変更してから、の代わりにをasync Task<string>使用することを意味します。await Task.Delay()Thread.Sleep()

非同期も作成したい場合Main()は、C#7.1以降を使用していれば可能です。

古いバージョンのC#を使用している場合は、次のようになります。あなたができることは、非同期を作成し、次にそれを実際にMainAsync()同期的に作成することです。これはメインスレッドがブロックされることを意味しますが、アプリケーションを存続させるためにそれが必要です。また、非同期と同期を混在させることは通常はお勧めできません(特に、デッドロックが発生することが多いため)が、この場合は問題ありません。Wait()Main()awaitWait()

非同期にする場合は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!";
    }
}
于 2012-11-28T18:18:44.923 に答える
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操作を表すオブジェクトを 返します。が戻るtask.Resultまで、現在のスレッドをブロックします。DoWork()

于 2012-11-28T07:25:09.577 に答える