ASP.NET Coreマルチスレッド非同期プログラミング

6754 ワード

@ASP.NET Coreマルチスレッド非同期プログラミング同期プログラミング同期プログラミング同期プログラミングは、単一スレッドにとって、私たちが作成したコンソールプログラムのように、mainメソッドを入口として、私たちが作成したコードを順番に実行します.非同期プログラミングは、マルチスレッドにとって、異なるスレッドを作成することによって、複数のタスクの並列実行を実現する.
スレッドNet 1.0はSystemをリリースした.Threadingでは、Thread、ThreadStartなどの多くのタイプの作成スレッドが表示されます.
プライマリ・スレッドは、Windowsプロセスごとに、プログラム・エントリ・ポイントとして使用されるプライマリ・スレッドを適切に含んでいます.プロセスのエントリポイントが作成する最初のスレッドをプライマリスレッドと呼ぶ.Net実行プログラム(コンソール、Windows Form、Wpfなど)は、Main()メソッドをプログラムエントリポイントとして使用します.メソッドが呼び出されると、プライマリ・スレッドが作成されます.
作業者スレッド主スレッドによって作成されたスレッドは、作業者スレッドと呼ばれ、特定のタスクを実行するために使用されます.
フロントスレッドのデフォルトではThreadが使用されます.Start()メソッドで作成されたスレッドはすべてフロントスレッドです.フロントスレッドはアプリケーションの終了を阻止し、すべてのフロントスレッドが実行された場合にのみCLRがアプリケーション(すなわち、ベアラをアンインストールしたアプリケーションドメイン)を閉じることができます.フロントスレッドも作業者スレッドに属します.
バックグラウンドスレッドバックグラウンドスレッドはアプリケーションの終了に影響しません.すべてのフロントスレッドが実行されると、バックグラウンドスレッドは実行されるかどうかにかかわらず終了します.一般的にバックグラウンドスレッドは、メールボックスが一定時間ごとにメールをチェックしたり、天気アプリケーションが一定時間ごとに天気を更新したりするなど、重要ではないタスクを行うために使用されます.バックグラウンドスレッドも作業者スレッドに属します.
//メインスレッドエントリstatic void Main(string[]args){Console.WriteLine(「メインスレッド開始!」);
        //        
        Thread t1 = new Thread(Task1);
        t1.Start();

        //        
        Thread t2 = new Thread(new ParameterizedThreadStart(Task2));
        t2.IsBackground = true;//       
        t2.Start("  ");
    }

    private static void Task1()
    {
        Thread.Sleep(1000);//      ,  1s
        Console.WriteLine("       !");
    }

    private static void Task2(object data)
    {
        Thread.Sleep(2000);//      ,  2s
        Console.WriteLine("       !" + data);
    }

111.PNG実行検出では、【バックグラウンドスレッドが呼び出された】は表示されません.すべてのフロントスレッドが実行されると、アプリケーションは閉じられ、すべてのバックグラウンドスレッドが実行されるのを待つことはないので、表示されません.
スレッドstatic void Main(){new Thread(Go).Start();//.NET 1.0からあるTask.Factory.StartNew(Go);//.NET 4.0はTPL Task.Run(new Action(Go));//.NET 4.5はRunのメソッドを追加しました}
public static void Go(){Console.WriteLine("私は別のスレッドです");}Threadのインスタンスを作成した後、手動で起動するStartメソッドが必要です.しかしTaskではStartNewとRunが同時に新しいスレッドを作成し、すぐに起動します.
スレッドプールスレッドプールは、突然大量に爆発するスレッドのために設計され、限られたいくつかの固定スレッドが大量の操作サービスを提供することで、スレッドの作成と破棄に要する時間を短縮し、効率を向上させることが、スレッドプールの主なメリットです.ThreadPoolは、複数のタスクを同時に実行し、実行時間が長くなく、互いに干渉しないシーンに適しています.スレッドプールで作成されたタスクはバックグラウンドタスクであることに注意してください.スレッドの作成はリソースを比較的占有することである.NETはスレッドプールを提供し、スレッドの作成と管理を支援します.Taskはデフォルトではスレッドプールを直接使用しますが、Threadは使用しません.Taskを使わずにスレッドプールを使いたい場合は、ThreadPoolクラスを使うことができます.
static void Main(){Console.WriteLine(「私はメインスレッド:Thread Id{0}」,Thread.CurrentThread.ManagedThreadId);ThreadPool.QueueUserWorkItem(Go);
Console.ReadLine();

}
public static void Go(object data){Console.WriteLine(「私は別のスレッド:Thread Id{0}」,Thread.CurrentThread.ManagedThreadId);}戻り値Taskには戻り値があります.
static void Main()/GetDayOfThisWeekは別のスレッドでvar dayName=Task.Run(()=>{return GetDayOfThisWeek();})を実行します.Console.WriteLine(「今日は:{0}」,dayName.Result);}並列タスク(Task)およびTaskベースの非同期プログラミング(asynchronously)は.NET Frameworkにはすでにあります.NET Coreプラットフォームの下でも同様の機能の実現があり、以下に通過する.NET Core WebAPI、Taskの使用を紹介します.resultの同期プログラミングおよびawaitを用いた非同期プログラミングモデル.
Task.Result .Net 4.0はSystemを導入する.Threading.Tasksは,スレッドとスレッドプールと直接付き合うことなく,非同期プログラミングを行う方法を簡略化した.System.Threading.Tasksのタイプをタスクパラレルライブラリ(TPL)と呼ぶ.TPLはCLRスレッドプール(TPLを使用して作成されたスレッドがバックグラウンドスレッドであることを示す)を使用して、アプリケーションの動作を使用可能なCPUに自動的に割り当てます.
Resultメソッドは、Taskが実行した結果を次のコードで返すことができます.
[HttpGet] public static async Task GetJsonAsync(Uri uri) { using (var client = new HttpClient()) { var jsonString = await client.GetStringAsync(uri); return JObject.Parse(jsonString); } }
public class MyController : ApiController { public string Get() { var jsonTask = GetJsonAsync(…); return jsonTask.Result.ToString(); } } しかしASP.NET Coreのwebapiでresultメソッドを使用してtask出力値を取得すると、現在のAPIスレッドのブロックがtask実行が完了してから続行されます.次のコードにより、getメソッドにはスレッドがあり、新しいスレッドを呼び出してtask(taskcaller)を実行し、taskを実行する際にtaskの実行結果を待つ必要があるため、getメソッドの実行スレッドがresult結果出力まで待機し、このスレッドはメソッドを継続的に完了することを証明することができる.
[Route("api/[controller])]public class ValuesController:Controller{//GET:api/[HttpGet("get")]public async Task Get(){var info=string.Format("api実行スレッド:{0},Thread.CurrentThread.ManagedThread.var infoTask = TaskCaller().Result;//Resultの使用
        var infoTaskFinished = string.Format("api    (task     ):{0}", Thread.CurrentThread.ManagedThreadId);
        return string.Format("{0},{1},{2}", info, infoTask, infoTaskFinished);
    }

    private async Task TaskCaller()
    {
        await Task.Delay(5000);
        return string.Format("task     :{0}", Thread.CurrentThread.ManagedThreadId);
    }
}

12.PNG async&await C#asyncキーワードは、メソッド、Lambda式、または匿名メソッドが自動的に非同期で呼び出されることを指定するために使用されます.async/awaitは非同期呼び出しのための形式であり、内部はスレッドプールで管理されています.awaitを使用すると、await taskcall()を呼び出すときにgetプライマリメソッドスレッドがブロックされず、プライマリメソッドスレッドが解放され、新しいスレッド実行がtaskを完了した後もawaitを実行し続けたコードはスレッド切替オーバーヘッドを低減し、以前のスレッドは空きました.
[Route("api/[controller])]public class ValuesController:Controller{//GET:api/[HttpGet("get")]public async Task Get(){var info=string.Format("api実行スレッド:{0},Thread.CurrentThread.ManagedThread.var infoTask = await TaskCaller();//awaitの使用
        var infoTaskFinished = string.Format("api    (task     ):{0}", Thread.CurrentThread.ManagedThreadId);
        return string.Format("{0},{1},{2}", info, infoTask, infoTaskFinished);
    }

    private async Task TaskCaller()
    {
        await Task.Delay(5000);
        return string.Format("task     :{0}", Thread.CurrentThread.ManagedThreadId);
    }
}

11.PNG
以上のように、最初はスレッド10で実行されたが、asyncメソッドで実行されるオンラインスレッド8にジャンプし、awaitを使用していない場合、メインスレッドは停止せず、asyncがawaitメソッドを使用するまで自分の道を下り、次のコードもサブスレッドに渡された.
なぜサブスレッド処理に渡されたのかというと,await前後のコードがブロック化され,awaitのtaskがスレッドプールに渡され,スレッドプールが実行された後moveNextメソッドが行われ,await後のコードが引き続き実行されるという記事がある.この文章を読むことができるhttp://www.cnblogs.com/vd630/p/4596203.html Task.resultはawaitキーワードと同様の機能を持っていて、タスクの戻り値を取得することができるが、本質的にTask.resultは、タスクの実行が完了するまで外層関数実行スレッドをブロックしますが、awaitキーワードを使用する外層関数スレッドはブロックされず、タスク実行スレッドによってawait後のコードを実行します.
デフォルトで作成されたThreadはフロントスレッドで、作成されたTaskはバックグラウンドスレッドです.ThreadPoolが作成したスレッドはすべてバックグラウンドスレッドです.タスクパラレルライブラリ(TPL)は、スレッドプール技術を使用します.asyncタグを呼び出すメソッドは、最初は同期して実行され、awaitタグのメソッドの非同期タスクが実行された場合にのみ保留されます.asyncとawaitの利点はASP.NET MVCは、例えばasyncのアクションを使用しない場合、Wokerスレッドで実行されます.Webサービスにアクセスしたり、ファイルを読んだりすると、このWorkerスレッドがブロックされます.
async/awaitを使用すると、Webサービスにアクセスするときに現在のworkerスレッドを解放し、スレッドプールに戻すことができ、他のリクエストを処理することができます.Webサービスが結果を返すと、スレッドプールに新しいwokerスレッドをランダムに持って行って実行し続けます.すなわち,我々はその部分の待ち時間を減らし,スレッドを十分に利用した.
***同期コードと非同期コードをできるだけ混在させないで、非同期にするには最後まで非同期にしてください.そうしないと、異常なキャプチャ、デッドロックなどの原因でアプリケーションがクラッシュする可能性があります.