NET 4パラレル(マルチコア)プログラミングシリーズの二はTaskから始まります。

14178 ワード

本論文は、http://www.cnblogs.com/yanyangtian/archive/2010/05/22/1741379.htmlから回転する。
NET 4パラレル(マルチコア)プログラミングシリーズの二はTaskから始まります。
         前書き:私達は一歩ずつ簡単なことから話し始めて、やはり私のずっとの方式をそのまま使います。    この文章の議題は以下の通りです。    1.Task基礎紹介    2.Taskの作成
    3.Taskの実行結果を取得する
4.詳細を追加する
 
シリーズの記事リンク:
NET 4パラレル(マルチコア)プログラミングシリーズの一つの入門紹介
NET 4パラレル(マルチコア)プログラミングシリーズの二はTaskから始まります。 
NET 4パラレル(マルチコア)プログラミングシリーズの3つがTaskからキャンセルされます。 
NET 4パラレル(マルチコア)プログラミングシリーズの4つのTaskの休止 
NETパラレル(マルチコア)プログラミングシリーズの五つのTask実行と異常処理 
NETパラレル(マルチコア)プログラミングシリーズの六Task基礎部分完結編 
NETパラレル(マルチコア)プログラミングシリーズの7つの共有データ問題と解決概要
 
 
 
    1.Task基礎紹介
 
    まず、簡単なコードを見に来ました。   
    ここで示されているのは簡単なコードだけで,並列プログラミングの特徴を示すことができない。しかし、私たちはやはり基本から見て、ゆっくりと深い話題に入ります。         NETのマルチスレッドプログラムを使ったことがあると、比較してみると、このコードは下の層ではマルチスレッドを使っていますが、書き方はかなり簡略化されていて、コードの1行が並列プログラミングされています。         次はTask類から話します。    TaskクラスはTask Programming Library(TPL)の中で最も核心的なクラスです。以下では、いくつかの方法を使って、異なるタイプのTaskを作成し、Taskをキャンセルし、Taskの実行が完了するのを待って、Taskの実行後の結果と異常を取得して処理する方法を示します。    討論を始める前に、まず前のコードを素早く見ます。       この名前空間は私達が後で並列プログラミングについて話しています。この空間は並列プログラミングに関連する多くの種類を含んでいる。    もう一つの名前空間はSystem.Threadingです。みんなはこれに慣れているはずです。前のマルチスレッドプログラミングはよく使われています。この空間には並列プログラミングでデータを調整するためのいくつかの種類が含まれています。    上のコードの中で、一番主要なコードは以下の通りです。   
Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Hello World");
            });
 
    私たちは静的な方法を使います。Task.Factory.StartNew()は最も簡単なTaskを作成しました。スクリーンで一言印刷します。このコードは確かに簡単です。しかも、入力と返却の結果がありません。    次に私達は正式に議題に入ります。    
2.Taskの作成   
       単純なTaskを作成するだけなら、私たちはこのTaskのために実行体を提供すればいいです。実行体はdelegateまたはactionに委託することができます。以前に示したコードはTaskの実行体としてLamban表現を採用したものです。    2.1簡単なTaskを作成する
 
    簡単なTaskを実行するために、以下のステップが一般的に行われる。    まず、Taskクラスのインスタンスを作成します。    そして、System.アクションの依頼が入ってきました。この依頼の方法はこのTaskが実行する時に実行する方法です。そして、この依頼はTask構成関数のパラメータとして入ってくる必要があります。私たちは着信依頼をパラメータとして使う場合には、匿名依頼、ラムダン表現、またはどのような方法を示す依頼が入るかのような方法があります。    最後に、TaskのインスタンスのStart()方法を呼び出して実行する。         このTaskの例が実行されると、それは内部のtask schedulerに渡されます。このschedulerは私たちが作成したtaskを下のスレッドに渡して実行します。    コードを見てみます。   
using System;
using System.Threading.Tasks;
namespace Listing_02
{
    class Listing_02
    {
        static void Main(string[] args)
        {

            // use an Action delegate and a named method
            Task task1 = new Task(new Action(printMessage));
            // use a anonymous delegate
            Task task2 = new Task(delegate
            {
                printMessage();
            });

            // use a lambda expression and a named method
            Task task3 = new Task(() => printMessage());
            // use a lambda expression and an anonymous method
            Task task4 = new Task(() =>
            {
                printMessage();
            });

            task1.Start();
            task2.Start();
            task3.Start();
            task4.Start();
            // wait for input before exiting
            Console.WriteLine("Main method complete. Press enter to finish.");
            Console.ReadLine();
        }

        static void printMessage()
        {
            Console.WriteLine("Hello World");
        }
    }
}
 
    皆さんが気づきましたか?上のコードはTaskを作成する方法と私達の前の第一段コードのTaskを作成する方法が違います。以前はTask.Factory.StartNew()方式で作成しました。この方法はTaskを作成してTaskを実行し始めました。実は両端のコードの結果は同じです。Taskを簡単に作成したいなら、Factory.NewStartを使って作成してもいいです。作成されたTaskに対してより多くのカスタムを加え、特定の属性を設定する場合は、まだ一歩ずつ私たちが話している手順に従ってください。(詳しくは後で紹介します)    2.1作成されたTask着信パラメータ
       私達の前提は、Taskを作成する時に、私達は構造関数の中からSystem.Actの依頼が入ってきました。もしいくつかのパラメータをTaskに伝えたいなら、System.Act<object>の依頼に入ることができます。例をあげます。   
using System;
using System.Threading.Tasks;
namespace Listing_04
{
    class Listing_04
    {
        static void Main(string[] args)
        {
            string[] messages = { "First task", "Second task",
"Third task", "Fourth task" };
            foreach (string msg in messages)
            {
                Task myTask = new Task(obj => printMessage((string)obj), msg);
                myTask.Start();
            }
            // wait for input before exiting
            Console.WriteLine("Main method complete. Press enter to finish.");
            Console.ReadLine();
        }

        static void printMessage(string message)
        {
            Console.WriteLine("Message: {0}", message);
        }
    }
}
 
         注意:私たちはパラメータを導入した後、パラメータを元のタイプに変換してから、対応する方法を呼び出さなければなりません。例えば、System.Actionに対応する方法はprint Message()方法であり、この方法の要求するパラメータタイプはstringであるため、stringに変換される。Taskに参素を伝えたいですが、System.Actを使うしかないです。    3.Taskの実行結果を取得する     
   Taskの結果を取得するには、Taskを作成する際に、Task<T>を用いてTaskを実行し、そのTがtask実行後に結果を返すタイプである。その後、Taskの例のResult属性を用いて結果を取得することができる。    コードは次のように表示されます。    
static void Main(string[] args)
        {
            // create the task
            Task<int> task1 = new Task<int>(() =>
            {
                int sum = 0;
                for (int i = 0; i < 100; i++)
                {
                    sum += i;
                }
                return sum;
            });
            
            task1.Start();
            // write out the result
            Console.WriteLine("Result 1: {0}", task1.Result);
            
            Console.ReadLine();
        }
 
    task実行が完了した後にのみ、Resultの値を取得することができます。    以下のコードは、Task.Factory.StartNew<T>()を介してどのようにTaskを作成するかを示し、結果を得る。    
  static void Main(string[] args)
        {
            // create the task
            Task<int> task1 = Task.Factory.StartNew<int>(() =>
            {
                int sum = 0;
                for (int i = 0; i < 100; i++)
                {
                    sum += i;
                }
                return sum;
            });

            // write out the result
            Console.WriteLine("Result 1: {0}", task1.Result);
            
            Console.ReadLine();
        }
 
4.詳細を追加する  
Taskを創建する時、Taskはたくさんの構造関数の重み付けがあります。一つの主要な重み付けはTaskCreateOptionsに入ってくる列挙です。          TaskCreateOptions.None:デフォルトでTaskを作成します。    TaskCreateOptions.PreferFairness:schedulerに対してできるだけ公平にTaskを実行するように要求します。    TaskCreateOptions.LongRunning:Taskは時間がかかると宣言しました。    TaskCreateOptions.AttachToPartent:Taskは入れ子ができるので、このエニュメレーションは一つの子taskを父taskに追加します。    最後に述べたいのは、Taskの実行体でTask.CurrentIdを使ってTaskの一意の表示ID(int)を返すことができるということです。Taskで体外でこの属性を使うとnullが得られます。    (WFをよく知っている友達は、TaskとWFの違いを比較できます。彼らのデザイン思想は近いと思います。)    今日はここまでです。ありがとうございます。 
 
著作権は小洋とブログ園が所有しています。転載は作者に出所を明記してください。
  http://www.cnblogs.com/yanyangtian