137

私はしばらくの間、.NET 4.5で簡単に作業できると思ったものを手に入れようとしていました

2 つの長時間実行タスクを同時に起動
し、C# 4.5 (RTM) の最適な方法で結果を収集したい

以下は機能しますが、次の理由で気に入りません。

  • 他のメソッドSleepができるように非同期メソッドになりたいawait
  • 不器用に見えるだけですTask.Run()
  • これは新しい言語機能をまったく使用していないと思います!

作業コード:

public static void Go()
{
    Console.WriteLine("Starting");

    var task1 = Task.Run(() => Sleep(5000));    
    var task2 = Task.Run(() => Sleep(3000));

    int totalSlept = task1.Result + task2.Result;

    Console.WriteLine("Slept for a total of " + totalSlept + " ms");
}

private static int Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    Thread.Sleep(ms);
    Console.WriteLine("Sleeping for " + ms + " FINISHED");
    return ms;
}

非動作コード:

更新:これは実際に機能し、正しい方法です。唯一の問題はThread.Sleep

を呼び出すとSleep(5000)すぐにタスクの実行が開始され、Sleep(1000)完了するまで実行されないため、このコードは機能しません。これは本当ですSleepasync、私はすぐに使用しawaitたり呼び出したりしていません。.Result

メソッドTask<T>を呼び出して非実行を取得する方法があるのではないかと考えたので、2 つのタスクを呼び出すことができましたが、非同期メソッドの呼び出しから取得する方法がわかりません。asyncStart()Task<T>

public static void Go()
{
    Console.WriteLine("Starting");

    var task1 = Sleep(5000);    // blocks
    var task2 = Sleep(1000);

    int totalSlept = task1.Result + task2.Result;

    Console.WriteLine("Slept for " + totalSlept + " ms");
}

private static async Task<int> Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    Thread.Sleep(ms);
    return ms;
}
4

6 に答える 6

136
async Task<int> LongTask1() { 
  ...
  return 0; 
}

async Task<int> LongTask2() { 
  ...
  return 1; 
}

...
{
   Task<int> t1 = LongTask1();
   Task<int> t2 = LongTask2();
   await Task.WhenAll(t1,t2);
   //now we have t1.Result and t2.Result
}
于 2012-11-24T14:20:18.630 に答える
3

Sleepメソッドは非同期ですが、そうではThread.Sleepありません。非同期の全体的な考え方は、複数のスレッドを開始するのではなく、単一のスレッドを再利用することです。Thread.Sleep への同期呼び出しを使用してブロックしたため、機能しません。

これThread.Sleepは、実際にやりたいことを単純化したものだと思います。実際の実装を非同期メソッドとしてコーディングできますか?

複数の同期ブロッキング呼び出しを実行する必要がある場合は、他の場所を見てください!

于 2012-09-09T21:25:19.267 に答える
2

この点に答えるには:

Sleep を非同期メソッドにして、他のメソッドを待機できるようにしたい

Sleep次のように関数を書き直すことができます。

private static async Task<int> Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    var task = Task.Run(() => Thread.Sleep(ms));
    await task;
    Console.WriteLine("Sleeping for " + ms + "END");
    return ms;
}

static void Main(string[] args)
{
    Console.WriteLine("Starting");

    var task1 = Sleep(2000);
    var task2 = Sleep(1000);

    int totalSlept = task1.Result +task2.Result;

    Console.WriteLine("Slept for " + totalSlept + " ms");
    Console.ReadKey();
}

このコードを実行すると、次のように出力されます。

Starting
Sleeping for 2000
Sleeping for 1000
*(one second later)*
Sleeping for 1000END
*(one second later)*
Sleeping for 2000END
Slept for 3000 ms
于 2013-06-12T22:38:31.270 に答える
2

今週末です!

    public async void Go()
    {
        Console.WriteLine("Start fosterage...");

        var t1 = Sleep(5000, "Kevin");
        var t2 = Sleep(3000, "Jerry");
        var result = await Task.WhenAll(t1, t2);

        Console.WriteLine($"My precious spare time last for only {result.Max()}ms");
        Console.WriteLine("Press any key and take same beer...");
        Console.ReadKey();
    }

    private static async Task<int> Sleep(int ms, string name)
    {
            Console.WriteLine($"{name} going to sleep for {ms}ms :)");
            await Task.Delay(ms);
            Console.WriteLine("${name} waked up after {ms}ms :(";
            return ms;
    }
于 2013-12-14T15:47:15.927 に答える
0

この記事は、多くのことを説明するのに役立ちました。FAQ風です。

非同期/待機に関するよくある質問

この部分では、同じ元のスレッドで実行される理由を説明してThread.Sleepいます。最初の混乱につながります。

「async」キーワードにより、メソッドの呼び出しが ThreadPool のキューに入れられますか? 新しいスレッドを作成するには? 火星にロケット船を打ち上げるには?

いいえ、いいえ、いいえ。前の質問を参照してください。「async」キーワードは、「await」がメソッド内で使用される可能性があることをコンパイラに示します。これにより、メソッドは待機ポイントで一時停止し、待機中のインスタンスが完了すると非同期で実行が再開されます。これが、「async」としてマークされたメソッド内に「await」がない場合、コンパイラが警告を発行する理由です。

于 2012-09-10T01:00:43.783 に答える