私はC#5.0で非同期/待機について学び始めていますが、まったく理解していません。並列処理にどのように使用できるかわかりません。次の非常に基本的なプログラムを試しました。
_using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Task task1 = Task1();
Task task2 = Task2();
Task.WaitAll(task1, task2);
Debug.WriteLine("Finished main method");
}
public static async Task Task1()
{
await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
Debug.WriteLine("Finished Task2");
}
}
}
_
このプログラムはTask.WaitAll()
の呼び出しをブロックするだけで終了することはありませんが、その理由はわかりません。私は単純なものを見逃しているだけであるか、またはこれに関する適切なメンタルモデルを持っていないに違いないと確信しており、世の中にあるブログやMSDNの記事はどれも役に立たない。
async
/await
の概要 から始め、 TAPに関するMSDN公式ドキュメント でフォローアップすることをお勧めします。
私のイントロのブログ投稿で言及したように、TPLからの持ち越しであり、純粋なTask
コードでは使用できないasync
メンバーがいくつかあります。 new Task
およびTask.Start
は、Task.Run
(またはTaskFactory.StartNew
)に置き換える必要があります。同様に、Thread.Sleep
はTask.Delay
に置き換える必要があります。
最後に、Task.WaitAll
を使用しないことをお勧めします。コンソールアプリは、Task.WhenAll
を使用する単一のWait
でTask
する必要があります。これらすべての変更により、コードは次のようになります。
class Program
{
static void Main(string[] args)
{
MainAsync().Wait();
}
public static async Task MainAsync()
{
Task task1 = Task1();
Task task2 = Task2();
await Task.WhenAll(task1, task2);
Debug.WriteLine("Finished main method");
}
public static async Task Task1()
{
await Task.Delay(5000);
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Delay(10000);
Debug.WriteLine("Finished Task2");
}
}
タスククラスは非同期タスクラッパーです。 Thread.Sleep(1000)は、実行中のスレッドを1秒間停止できます。一方、Task.Delay(1000)は現在の作業を停止しません。コードを参照してください:
public static void Main(string[] args){
TaskTest();
}
private static void TaskTest(){
Task.Delay(5000);
System.Console.WriteLine("task done");
}
実行すると、「タスク完了」がすぐに表示されます。したがって、Taskのすべてのメソッドは非同期であると想定できます。 TaskTest()をTask.Run(()=> TaskTest())に置き換えた場合、Console.ReadLine();を追加するまで、完了したタスクはまったく表示されません。 Runメソッドの後。
内部的に、タスククラスはステートマシンのスレッド状態を表します。状態マシンのすべての状態には、開始、遅延、キャンセル、停止などのいくつかの状態があります。
さて、すべてのTaskが非同期かどうか疑問に思うかもしれませんが、Task.Delayの目的は何ですか?次に、非同期と待機を使用して、実行中のスレッドを実際に遅延させましょう
public static void Main(string[] args){
TaskTest();
System.Console.WriteLine("main thread is not blocked");
Console.ReadLine();
}
private static async void TaskTest(){
await Task.Delay(5000);
System.Console.WriteLine("task done");
}
async tell caller、私は非同期メソッドです。待ってはいけません。 TaskTest()内で待機して、非同期タスクを待機するように要求します。これで、実行後、プログラムはタスク完了テキストを表示するために5秒待機します。
タスクはステートマシンであるため、タスクの実行中にタスクをキャンセルする方法が必要です。
static CancellationTokenSource tokenSource = new CancellationTokenSource();
public static void Main(string[] args){
TaskTest();
System.Console.WriteLine("main thread is not blocked");
var input=Console.ReadLine();
if(input=="stop"){
tokenSource.Cancel();
System.Console.WriteLine("task stopped");
}
Console.ReadLine();
}
private static async void TaskTest(){
try{
await Task.Delay(5000,tokenSource.Token);
}catch(TaskCanceledException e){
//cancel task will throw out a exception, just catch it, do nothing.
}
System.Console.WriteLine("task done");
}
これで、プログラムの実行中に「停止」を入力して、遅延タスクをキャンセルできます。
タスクは実行を開始しないため、終了することはありません。
_Task.Factory.StartNew
_でタスクを作成して開始します。
_public static async Task Task1()
{
await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
Debug.WriteLine("Finished Task2");
}
_
サイドノートとして、あなたが本当に非同期メソッドで一時停止しようとしているのであれば、スレッド全体をブロックする必要はなく、単に_Task.Delay
_を使用してください
_public static async Task Task1()
{
await Task.Delay(TimeSpan.FromSeconds(5));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Delay(TimeSpan.FromSeconds(10));
Debug.WriteLine("Finished Task2");
}
_
非同期と待機は、タスク(スレッド)の完了後に制御を再開するコード位置をマークするマーカーです。概念をデモ形式で説明する詳細なYouTubeビデオがあります http://www.youtube.com/watch?v=V2sMXJnDEjM
必要に応じて、このcoodeprojectの記事を読んで、同じことをより視覚的に説明することもできます。 http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features#Feature1:- “ Async” and“ Await”(Codemarkers)