中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

安慶網(wǎng)站建設(shè)服務(wù)網(wǎng)蘇州關(guān)鍵詞搜索排名

安慶網(wǎng)站建設(shè)服務(wù)網(wǎng),蘇州關(guān)鍵詞搜索排名,怎么檢測網(wǎng)站是否安全,開發(fā)公司贈送閣樓視同銷售本文內(nèi)容 隱式創(chuàng)建和運行任務(wù)顯式創(chuàng)建和運行任務(wù)任務(wù) ID任務(wù)創(chuàng)建選項任務(wù)、線程和區(qū)域性創(chuàng)建任務(wù)延續(xù)創(chuàng)建分離的子任務(wù)創(chuàng)建子任務(wù)等待任務(wù)完成組合任務(wù)處理任務(wù)中的異常取消任務(wù)TaskFactory 類無委托的任務(wù)自定義計劃程序相關(guān)數(shù)據(jù)結(jié)構(gòu)自定義任務(wù)類型 任務(wù)并行庫 (TPL) 以“任…

本文內(nèi)容

  1. 隱式創(chuàng)建和運行任務(wù)
  2. 顯式創(chuàng)建和運行任務(wù)
  3. 任務(wù) ID
  4. 任務(wù)創(chuàng)建選項
  5. 任務(wù)、線程和區(qū)域性
  6. 創(chuàng)建任務(wù)延續(xù)
  7. 創(chuàng)建分離的子任務(wù)
  8. 創(chuàng)建子任務(wù)
  9. 等待任務(wù)完成
  10. 組合任務(wù)
  11. 處理任務(wù)中的異常
  12. 取消任務(wù)
  13. TaskFactory 類
  14. 無委托的任務(wù)
  15. 自定義計劃程序
  16. 相關(guān)數(shù)據(jù)結(jié)構(gòu)
  17. 自定義任務(wù)類型

任務(wù)并行庫 (TPL) 以“任務(wù)”的概念為基礎(chǔ),后者表示異步操作。 在某些方面,任務(wù)類似于線程或?ThreadPool?工作項,但是抽象級別更高。 術(shù)語“任務(wù)并行”是指一個或多個獨立的任務(wù)同時運行。 任務(wù)提供兩個主要好處:

  • 系統(tǒng)資源的使用效率更高,可伸縮性更好。

    在后臺,任務(wù)排隊到已使用算法增強的?ThreadPool,這些算法能夠確定線程數(shù)并隨之調(diào)整。 這些算法提供負載平衡以實現(xiàn)吞吐量最大化。 此進程會使任務(wù)相對輕量,你可以創(chuàng)建很多任務(wù)以啟用細化并行。

  • 對于線程或工作項,可以使用更多的編程控件。

    任務(wù)和圍繞它們生成的框架提供了一組豐富的 API,這些 API 支持等待、取消、繼續(xù)、可靠的異常處理、詳細狀態(tài)、自定義計劃等功能。

出于這兩個原因,在 .NET 中,TPL 是用于編寫多線程、異步和并行代碼的首選 API。

1、隱式創(chuàng)建和運行任務(wù)

Parallel.Invoke?方法提供了一種簡便方式,可同時運行任意數(shù)量的任意語句。 只需為每個工作項傳入?Action?委托即可。 創(chuàng)建這些委托的最簡單方式是使用 lambda 表達式。 lambda 表達式可調(diào)用指定的方法,或提供內(nèi)聯(lián)代碼。 下面的示例演示一個基本的?Invoke?調(diào)用,該調(diào)用創(chuàng)建并啟動同時運行的兩個任務(wù)。 第一個任務(wù)由調(diào)用名為?DoSomeWork?的方法的 lambda 表達式表示,第二個任務(wù)由調(diào)用名為?DoSomeOtherWork?的方法的 lambda 表達式表示。

?備注

本文檔使用 lambda 表達式在 TPL 中定義委托。?

Parallel.Invoke(() => DoSomeWork(), () => DoSomeOtherWork());

?備注

Invoke?在后臺創(chuàng)建的?Task?實例數(shù)不一定與所提供的委托數(shù)相等。 TPL 可能會使用各種優(yōu)化,特別是對于大量的委托。

為了更好地控制任務(wù)執(zhí)行或從任務(wù)返回值,必須更加顯式地使用?Task?對象。

2、顯式創(chuàng)建和運行任務(wù)

不返回值的任務(wù)由?System.Threading.Tasks.Task?類表示。 返回值的任務(wù)由?System.Threading.Tasks.Task<TResult>?類表示,該類從?Task?繼承。 任務(wù)對象處理基礎(chǔ)結(jié)構(gòu)詳細信息,并提供可在任務(wù)的整個生存期內(nèi)從調(diào)用線程訪問的方法和屬性。 例如,可以隨時訪問任務(wù)的?Status?屬性,以確定它是已開始運行、已完成運行、已取消還是引發(fā)了異常。 狀態(tài)由?TaskStatus?枚舉表示。

在創(chuàng)建任務(wù)時,你賦予它一個用戶委托,該委托封裝該任務(wù)將執(zhí)行的代碼。 該委托可以表示為命名的委托、匿名方法或 lambda 表達式。 lambda 表達式可以包含對命名方法的調(diào)用,如下面的示例所示。 該示例包含對?Task.Wait?方法的調(diào)用,以確保任務(wù)在控制臺模式應(yīng)用程序結(jié)束之前完成執(zhí)行。

using System;
using System.Threading;
using System.Threading.Tasks;public class Lambda
{public static void Main(){Thread.CurrentThread.Name = "Main";// Create a task and supply a user delegate by using a lambda expression.Task taskA = new Task( () => Console.WriteLine("Hello from taskA."));// Start the task.taskA.Start();// Output a message from the calling thread.Console.WriteLine("Hello from thread '{0}'.",Thread.CurrentThread.Name);taskA.Wait();}
}
// The example displays output as follows:
//       Hello from thread 'Main'.
//       Hello from taskA.
// or
//       Hello from taskA.
//       Hello from thread 'Main'.

你還可以使用?Task.Run?方法通過一個操作創(chuàng)建并啟動任務(wù)。 無論是哪個任務(wù)計劃程序與當(dāng)前線程關(guān)聯(lián),Run?方法都將使用默認的任務(wù)計劃程序來管理任務(wù)。 不需要對任務(wù)的創(chuàng)建和計劃進行更多控制時,首選?Run?方法創(chuàng)建并啟動任務(wù)。

using System;
using System.Threading;
using System.Threading.Tasks;namespace Run;public class Example
{public static void Main(){Thread.CurrentThread.Name = "Main";// Define and run the task.Task taskA = Task.Run( () => Console.WriteLine("Hello from taskA."));// Output a message from the calling thread.Console.WriteLine("Hello from thread '{0}'.",Thread.CurrentThread.Name);taskA.Wait();}
}
// The example displays output as follows:
//       Hello from thread 'Main'.
//       Hello from taskA.
// or
//       Hello from taskA.
//       Hello from thread 'Main'.

你還可以使用?TaskFactory.StartNew?方法在一個操作中創(chuàng)建并啟動任務(wù)。 如下例所示,可以在以下情況下使用此方法:

  • 無需將創(chuàng)建與計劃分開,且需要額外的任務(wù)創(chuàng)建選項或需要使用特定的計劃程序。

  • 需要將其他狀態(tài)傳遞給可通過其?Task.AsyncState?屬性檢索的任務(wù)。

using System;
using System.Threading;
using System.Threading.Tasks;namespace TaskIntro;class CustomData
{public long CreationTime;public int Name;public int ThreadNum;
}public class AsyncState
{public static void Main(){Task[] taskArray = new Task[10];for (int i = 0; i < taskArray.Length; i++){taskArray[i] = Task.Factory.StartNew((Object obj) =>{CustomData data = obj as CustomData;if (data == null) return;data.ThreadNum = Thread.CurrentThread.ManagedThreadId;},new CustomData() { Name = i, CreationTime = DateTime.Now.Ticks });}Task.WaitAll(taskArray);foreach (var task in taskArray){var data = task.AsyncState as CustomData;if (data != null)Console.WriteLine("Task #{0} created at {1}, ran on thread #{2}.",data.Name, data.CreationTime, data.ThreadNum);}}
}
// The example displays output like the following:
//     Task #0 created at 635116412924597583, ran on thread #3.
//     Task #1 created at 635116412924607584, ran on thread #4.
//     Task #2 created at 635116412924607584, ran on thread #4.
//     Task #3 created at 635116412924607584, ran on thread #4.
//     Task #4 created at 635116412924607584, ran on thread #3.
//     Task #5 created at 635116412924607584, ran on thread #3.
//     Task #6 created at 635116412924607584, ran on thread #4.
//     Task #7 created at 635116412924607584, ran on thread #4.
//     Task #8 created at 635116412924607584, ran on thread #3.
//     Task #9 created at 635116412924607584, ran on thread #4.

Task?和?Task<TResult>?均公開靜態(tài)?Factory?屬性,該屬性返回?TaskFactory?的默認實例,因此你可以調(diào)用該方法為?Task.Factory.StartNew()。 此外,在以下示例中,由于任務(wù)的類型為?System.Threading.Tasks.Task<TResult>,因此每個任務(wù)都具有包含計算結(jié)果的公共?Task<TResult>.Result?屬性。 任務(wù)以異步方式運行,可以按任意順序完成。 如果在計算完成之前訪問?Result?屬性,則該屬性將阻止調(diào)用線程。

使用 lambda 表達式創(chuàng)建委托時,你有權(quán)訪問源代碼中當(dāng)時可見的所有變量。 然而,在某些情況下,特別是在循環(huán)中,lambda 不按照預(yù)期的方式捕獲變量。 它僅捕獲變量的引用,而不是它每次迭代后更改的值。 以下示例演示了該問題。 它將循環(huán)計數(shù)器傳遞給實例化?CustomData?對象并使用循環(huán)計數(shù)器作為對象標識符的 lambda 表達式。 如示例輸出所示,每個?CustomData?對象都具有相同的標識符。

using System;
using System.Threading;
using System.Threading.Tasks;namespace Example.Iterations;class CustomData
{public long CreationTime;public int Name;public int ThreadNum;
}public class IterationTwo
{public static void Main(){// Create the task object by using an Action(Of Object) to pass in the loop// counter. This produces an unexpected result.Task[] taskArray = new Task[10];for (int i = 0; i < taskArray.Length; i++) {taskArray[i] = Task.Factory.StartNew( (Object obj) => {var data = new CustomData() {Name = i, CreationTime = DateTime.Now.Ticks};data.ThreadNum = Thread.CurrentThread.ManagedThreadId;Console.WriteLine("Task #{0} created at {1} on thread #{2}.",data.Name, data.CreationTime, data.ThreadNum);},i );}Task.WaitAll(taskArray);}
}
// The example displays output like the following:
//       Task #10 created at 635116418427727841 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427737842 on thread #4.
//       Task #10 created at 635116418427727841 on thread #3.
//       Task #10 created at 635116418427747843 on thread #3.
//       Task #10 created at 635116418427747843 on thread #3.
//       Task #10 created at 635116418427737842 on thread #4.

通過使用構(gòu)造函數(shù)向任務(wù)提供狀態(tài)對象,可以在每次迭代時訪問該值。 以下示例在上一示例的基礎(chǔ)上做了修改,在創(chuàng)建?CustomData?對象時使用循環(huán)計數(shù)器,該對象繼而傳遞給 lambda 表達式。 如示例輸出所示,每個?CustomData?對象現(xiàn)在都具有唯一的一個標識符,該標識符基于該對象實例化時循環(huán)計數(shù)器的值。

using System;
using System.Threading;
using System.Threading.Tasks;class CustomData
{public long CreationTime;public int Name;public int ThreadNum;
}public class IterationOne
{public static void Main(){// Create the task object by using an Action(Of Object) to pass in custom data// to the Task constructor. This is useful when you need to capture outer variables// from within a loop.Task[] taskArray = new Task[10];for (int i = 0; i < taskArray.Length; i++) {taskArray[i] = Task.Factory.StartNew( (Object obj ) => {CustomData data = obj as CustomData;if (data == null)return;data.ThreadNum = Thread.CurrentThread.ManagedThreadId;Console.WriteLine("Task #{0} created at {1} on thread #{2}.",data.Name, data.CreationTime, data.ThreadNum);},new CustomData() {Name = i, CreationTime = DateTime.Now.Ticks} );}Task.WaitAll(taskArray);}
}
// The example displays output like the following:
//       Task #0 created at 635116412924597583 on thread #3.
//       Task #1 created at 635116412924607584 on thread #4.
//       Task #3 created at 635116412924607584 on thread #4.
//       Task #4 created at 635116412924607584 on thread #4.
//       Task #2 created at 635116412924607584 on thread #3.
//       Task #6 created at 635116412924607584 on thread #3.
//       Task #5 created at 635116412924607584 on thread #4.
//       Task #8 created at 635116412924607584 on thread #4.
//       Task #7 created at 635116412924607584 on thread #3.
//       Task #9 created at 635116412924607584 on thread #4.

此狀態(tài)作為參數(shù)傳遞給任務(wù)委托,并且可通過使用?Task.AsyncState?屬性從任務(wù)對象訪問。 以下示例在上一示例的基礎(chǔ)上演變而來。 它使用?AsyncState?屬性顯示關(guān)于傳遞到 lambda 表達式的?CustomData?對象的信息。

using System;
using System.Threading;
using System.Threading.Tasks;namespace TaskIntro;class CustomData
{public long CreationTime;public int Name;public int ThreadNum;
}public class AsyncState
{public static void Main(){Task[] taskArray = new Task[10];for (int i = 0; i < taskArray.Length; i++){taskArray[i] = Task.Factory.StartNew((Object obj) =>{CustomData data = obj as CustomData;if (data == null) return;data.ThreadNum = Thread.CurrentThread.ManagedThreadId;},new CustomData() { Name = i, CreationTime = DateTime.Now.Ticks });}Task.WaitAll(taskArray);foreach (var task in taskArray){var data = task.AsyncState as CustomData;if (data != null)Console.WriteLine("Task #{0} created at {1}, ran on thread #{2}.",data.Name, data.CreationTime, data.ThreadNum);}}
}
// The example displays output like the following:
//     Task #0 created at 635116412924597583, ran on thread #3.
//     Task #1 created at 635116412924607584, ran on thread #4.
//     Task #2 created at 635116412924607584, ran on thread #4.
//     Task #3 created at 635116412924607584, ran on thread #4.
//     Task #4 created at 635116412924607584, ran on thread #3.
//     Task #5 created at 635116412924607584, ran on thread #3.
//     Task #6 created at 635116412924607584, ran on thread #4.
//     Task #7 created at 635116412924607584, ran on thread #4.
//     Task #8 created at 635116412924607584, ran on thread #3.
//     Task #9 created at 635116412924607584, ran on thread #4.

3、任務(wù) ID

每個任務(wù)都獲得一個在應(yīng)用程序域中唯一標識自己的整數(shù) ID,可以使用?Task.Id?屬性訪問該 ID。 該 ID 可有效用于在 Visual Studio 調(diào)試器的“并行堆?!焙汀叭蝿?wù)”窗口中查看任務(wù)信息。 該 ID 是以惰性方式創(chuàng)建的,這意味著請求該 ID 時才會創(chuàng)建該 ID。 因此,每次運行程序時,任務(wù)可能具有不同的 ID。?

4、任務(wù)創(chuàng)建選項

創(chuàng)建任務(wù)的大多數(shù) API 提供接受?TaskCreationOptions?參數(shù)的重載。 通過指定下列某個或多個選項,可指示任務(wù)計劃程序在線程池中安排任務(wù)計劃的方式。 可以使用位 OR 運算組合選項。

下面的示例演示一個具有?LongRunning?和?PreferFairness?選項的任務(wù):

var task3 = new Task(() => MyLongRunningMethod(),TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
task3.Start();

5、任務(wù)、線程和區(qū)域性

每個線程都具有一個關(guān)聯(lián)的區(qū)域性和 UI 區(qū)域性,分別由?Thread.CurrentCulture?和?Thread.CurrentUICulture?屬性定義。 線程的區(qū)域性用在格式設(shè)置、分析、排序和字符串比較等操作中。 線程的 UI 區(qū)域性用于查找資源。

系統(tǒng)區(qū)域性定義線程的默認區(qū)域性和 UI 區(qū)域性。 但你可以使用?CultureInfo.DefaultThreadCurrentCulture?和?CultureInfo.DefaultThreadCurrentUICulture?屬性為應(yīng)用程序域中的所有線程指定默認區(qū)域性。 如果你顯式設(shè)置線程的區(qū)域性并啟動新線程,則新線程不會繼承正在調(diào)用的線程的區(qū)域性;相反,其區(qū)域性就是默認系統(tǒng)區(qū)域性。 但是,在基于任務(wù)的編程中,任務(wù)使用調(diào)用線程的區(qū)域性,即使任務(wù)在不同線程上以異步方式運行也是如此。

下面的示例提供了簡單的演示。 它將應(yīng)用的當(dāng)前區(qū)域性更改為法語(法國)。 如果法語(法國)已經(jīng)是當(dāng)前區(qū)域性,它會更改為英語(美國)。 然后,調(diào)用一個名為?formatDelegate?的委托,該委托返回在新區(qū)域性中格式化為貨幣值的數(shù)字。 無論委托是由任務(wù)同步調(diào)用還是異步調(diào)用,該任務(wù)都將使用調(diào)用線程的區(qū)域性。

using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;public class Example
{public static void Main(){decimal[] values = { 163025412.32m, 18905365.59m };string formatString = "C2";Func<String> formatDelegate = () => { string output = String.Format("Formatting using the {0} culture on thread {1}.\n",CultureInfo.CurrentCulture.Name,Thread.CurrentThread.ManagedThreadId);foreach (var value in values)output += String.Format("{0}   ", value.ToString(formatString));output += Environment.NewLine;return output;};Console.WriteLine("The example is running on thread {0}",Thread.CurrentThread.ManagedThreadId);// Make the current culture different from the system culture.Console.WriteLine("The current culture is {0}",CultureInfo.CurrentCulture.Name);if (CultureInfo.CurrentCulture.Name == "fr-FR")Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");elseThread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");Console.WriteLine("Changed the current culture to {0}.\n",CultureInfo.CurrentCulture.Name);// Execute the delegate synchronously.Console.WriteLine("Executing the delegate synchronously:");Console.WriteLine(formatDelegate());// Call an async delegate to format the values using one format string.Console.WriteLine("Executing a task asynchronously:");var t1 = Task.Run(formatDelegate);Console.WriteLine(t1.Result);Console.WriteLine("Executing a task synchronously:");var t2 = new Task<String>(formatDelegate);t2.RunSynchronously();Console.WriteLine(t2.Result);}
}
// The example displays the following output:
//         The example is running on thread 1
//         The current culture is en-US
//         Changed the current culture to fr-FR.
//
//         Executing the delegate synchronously:
//         Formatting using the fr-FR culture on thread 1.
//         163 025 412,32 €   18 905 365,59 €
//
//         Executing a task asynchronously:
//         Formatting using the fr-FR culture on thread 3.
//         163 025 412,32 €   18 905 365,59 €
//
//         Executing a task synchronously:
//         Formatting using the fr-FR culture on thread 1.
//         163 025 412,32 €   18 905 365,59 €

在 .NET Framework 4.6 之前的 .NET Framework 版本中,任務(wù)的區(qū)域性由它在其上運行的線程區(qū)域性確定,而不是調(diào)用線程的區(qū)域性。 對于異步任務(wù),任務(wù)使用的區(qū)域性可能不同于調(diào)用線程的區(qū)域性。

有關(guān)異步任務(wù)和區(qū)域性的詳細信息,請參閱?CultureInfo?一文中的“區(qū)域性和基于異步任務(wù)的操作”部分。

6、創(chuàng)建任務(wù)延續(xù)

使用?Task.ContinueWith?和?Task<TResult>.ContinueWith?方法,可以指定要在先行任務(wù)完成時啟動的任務(wù)。 延續(xù)任務(wù)的委托被傳遞給對先行任務(wù)的引用,以便它查看先行任務(wù)的狀態(tài)。 通過檢索?Task<TResult>.Result?屬性的值,可以將先行任務(wù)的輸出用作延續(xù)任務(wù)的輸入。

在下面的示例中,getData?任務(wù)通過調(diào)用?TaskFactory.StartNew<TResult>(Func<TResult>)?方法來啟動。 當(dāng)?processData?完成時,getData?任務(wù)自動啟動,當(dāng)?displayData?完成時,processData?啟動。?getData?產(chǎn)生一個整數(shù)數(shù)組,通過?processData?任務(wù)的?getData?屬性,Task<TResult>.Result?任務(wù)可訪問該數(shù)組。?processData?任務(wù)處理該數(shù)組并返回結(jié)果,結(jié)果的類型從傳遞到?Task<TResult>.ContinueWith<TNewResult>(Func<Task<TResult>,TNewResult>)?方法的 Lambda 表達式的返回類型推斷而來。?displayData?完成時,processData?任務(wù)自動執(zhí)行,而?Tuple<T1,T2,T3>?任務(wù)可通過?processData?任務(wù)的?displayData?屬性訪問由?processData?lambda 表達式返回的?Task<TResult>.Result?對象。?displayData?任務(wù)采用?processData?任務(wù)的結(jié)果。 它得出自己的結(jié)果,其類型以相似方式推斷而來,且可由程序中的?Result?屬性使用。

using System;
using System.Threading.Tasks;public class ContinuationOne
{public static void Main(){var getData = Task.Factory.StartNew(() => {Random rnd = new Random();int[] values = new int[100];for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++)values[ctr] = rnd.Next();return values;} );var processData = getData.ContinueWith((x) => {int n = x.Result.Length;long sum = 0;double mean;for (int ctr = 0; ctr <= x.Result.GetUpperBound(0); ctr++)sum += x.Result[ctr];mean = sum / (double) n;return Tuple.Create(n, sum, mean);} );var displayData = processData.ContinueWith((x) => {return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",x.Result.Item1, x.Result.Item2,x.Result.Item3);} );Console.WriteLine(displayData.Result);}
}
// The example displays output similar to the following:
//    N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82

因為?Task.ContinueWith?是實例方法,所以你可以將方法調(diào)用鏈接在一起,而不是為每個先行任務(wù)去實例化?Task<TResult>?對象。 以下示例與上一示例在功能上等同,唯一的不同在于它將對?Task.ContinueWith?方法的調(diào)用鏈接在一起。 通過方法調(diào)用鏈返回的?Task<TResult>?對象是最終延續(xù)任務(wù)。

using System;
using System.Threading.Tasks;public class ContinuationTwo
{public static void Main(){var displayData = Task.Factory.StartNew(() => {Random rnd = new Random();int[] values = new int[100];for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++)values[ctr] = rnd.Next();return values;} ).ContinueWith((x) => {int n = x.Result.Length;long sum = 0;double mean;for (int ctr = 0; ctr <= x.Result.GetUpperBound(0); ctr++)sum += x.Result[ctr];mean = sum / (double) n;return Tuple.Create(n, sum, mean);} ).ContinueWith((x) => {return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",x.Result.Item1, x.Result.Item2,x.Result.Item3);} );Console.WriteLine(displayData.Result);}
}
// The example displays output similar to the following:
//    N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82

使用?ContinueWhenAll?和?ContinueWhenAny?方法,可以從多個任務(wù)繼續(xù)。

7、創(chuàng)建分離的子任務(wù)

如果在任務(wù)中運行的用戶代碼創(chuàng)建一個新任務(wù),且未指定?AttachedToParent?選項,則該新任務(wù)不采用任何特殊方式與父任務(wù)同步。 這種不同步的任務(wù)類型稱為“分離的嵌套任務(wù)”或“分離的子任務(wù)”。 以下示例展示了創(chuàng)建一個分離子任務(wù)的任務(wù):

var outer = Task.Factory.StartNew(() =>
{Console.WriteLine("Outer task beginning.");var child = Task.Factory.StartNew(() =>{Thread.SpinWait(5000000);Console.WriteLine("Detached task completed.");});
});outer.Wait();
Console.WriteLine("Outer task completed.");
// The example displays the following output:
//    Outer task beginning.
//    Outer task completed.
//    Detached task completed.

?備注

父任務(wù)不會等待分離子任務(wù)完成。

8、創(chuàng)建子任務(wù)

如果任務(wù)中運行的用戶代碼在創(chuàng)建任務(wù)時指定了?AttachedToParent?選項,新任務(wù)就稱為父任務(wù)的附加子任務(wù)。 因為父任務(wù)隱式地等待所有附加子任務(wù)完成,所以你可以使用?AttachedToParent?選項表示結(jié)構(gòu)化的任務(wù)并行。 以下示例展示了創(chuàng)建 10 個附加子任務(wù)的父任務(wù)。 該示例調(diào)用?Task.Wait?方法來等待父任務(wù)完成。 它不必顯式等待附加子任務(wù)完成。

using System;
using System.Threading;
using System.Threading.Tasks;public class Child
{public static void Main(){var parent = Task.Factory.StartNew(() => {Console.WriteLine("Parent task beginning.");for (int ctr = 0; ctr < 10; ctr++) {int taskNo = ctr;Task.Factory.StartNew((x) => {Thread.SpinWait(5000000);Console.WriteLine("Attached child #{0} completed.",x);},taskNo, TaskCreationOptions.AttachedToParent);}});parent.Wait();Console.WriteLine("Parent task completed.");}
}
// The example displays output like the following:
//       Parent task beginning.
//       Attached child #9 completed.
//       Attached child #0 completed.
//       Attached child #8 completed.
//       Attached child #1 completed.
//       Attached child #7 completed.
//       Attached child #2 completed.
//       Attached child #6 completed.
//       Attached child #3 completed.
//       Attached child #5 completed.
//       Attached child #4 completed.
//       Parent task completed.

父任務(wù)可使用?TaskCreationOptions.DenyChildAttach?選項阻止其他任務(wù)附加到父任務(wù)。?

9、等待任務(wù)完成

System.Threading.Tasks.Task?和?System.Threading.Tasks.Task<TResult>?類型提供了?Task.Wait?方法的若干重載,以便能夠等待任務(wù)完成。 此外,使用靜態(tài)?Task.WaitAll?和?Task.WaitAny?方法的重載可以等待一批任務(wù)中的任一任務(wù)或所有任務(wù)完成。

通常,會出于以下某個原因等待任務(wù):

  • 主線程依賴于任務(wù)計算的最終結(jié)果。

  • 你必須處理可能從任務(wù)引發(fā)的異常。

  • 應(yīng)用程序可以在所有任務(wù)執(zhí)行完畢之前終止。 例如,執(zhí)行?Main(應(yīng)用程序入口點)中的所有同步代碼后,控制臺應(yīng)用程序?qū)⒔K止。

下面的示例演示不包含異常處理的基本模式:

Task[] tasks = new Task[3]
{Task.Factory.StartNew(() => MethodA()),Task.Factory.StartNew(() => MethodB()),Task.Factory.StartNew(() => MethodC())
};//Block until all tasks complete.
Task.WaitAll(tasks);// Continue on this thread...

某些重載允許你指定超時,而其他重載采用額外的?CancellationToken?作為輸入?yún)?shù),以便可以通過編程方式或根據(jù)用戶輸入來取消等待。

等待任務(wù)時,其實是在隱式等待使用?TaskCreationOptions.AttachedToParent?選項創(chuàng)建的該任務(wù)的所有子級。?Task.Wait?在該任務(wù)已完成時立即返回。?Task.Wait?方法將拋出由某任務(wù)引發(fā)的任何異常,即使?Task.Wait?方法是在該任務(wù)完成之后調(diào)用的。

10、組合任務(wù)

Task?和?Task<TResult>?類提供了多種方法來幫助組合多個任務(wù)。 這些方法實現(xiàn)常用模式并更好地利用 C#、Visual Basic 和 F# 提供的異步語言功能。 本節(jié)介紹了?WhenAll、WhenAny、Delay?和?FromResult?方法。

Task.WhenAll

Task.WhenAll?方法異步等待多個?Task?或?Task<TResult>?對象完成。 通過它提供的重載版本可以等待非均勻任務(wù)組。 例如,你可以等待多個?Task?和?Task<TResult>?對象在一個方法調(diào)用中完成。

Task.WhenAny

Task.WhenAny?方法異步等待多個?Task?或?Task<TResult>?對象中的一個完成。 與在?Task.WhenAll?方法中一樣,該方法提供重載版本,讓你能等待非均勻任務(wù)組。?WhenAny?方法在下列情境中尤其有用:

  • 冗余運算:請考慮可以用多種方式執(zhí)行的算法或運算。 你可使用?WhenAny?方法來選擇先完成的運算,然后取消剩余的運算。

  • 交錯運算:你可啟動必須完成的多項運算,并使用?WhenAny?方法在每項運算完成時處理結(jié)果。 在一項運算完成后,可以啟動一個或多個任務(wù)。

  • 限制運算:你可使用?WhenAny?方法通過限制并發(fā)運算的數(shù)量來擴展前面的情境。

  • 到期運算:你可使用?WhenAny?方法在一個或多個任務(wù)與特定時間后完成的任務(wù)(例如?Delay?方法返回的任務(wù))間進行選擇。 下節(jié)描述了?Delay?方法。

Task.Delay

Task.Delay?方法將生成在指定時間后完成的?Task?對象。 你可以使用此方法生成用于輪詢數(shù)據(jù)的循環(huán),指定超時,延遲處理用戶輸入等。

Task(T).FromResult

通過使用?Task.FromResult?方法,你可以創(chuàng)建包含預(yù)計算結(jié)果的?Task<TResult>?對象。 執(zhí)行返回?Task<TResult>?對象的異步運算,且已計算該?Task<TResult>?對象的結(jié)果時,此方法將十分有用。

11、處理任務(wù)中的異常

當(dāng)某個任務(wù)拋出一個或多個異常時,異常包裝在?AggregateException?異常中。 該異常會傳播回與任務(wù)聯(lián)接的線程。 通常,該線程是等待任務(wù)完成的線程或訪問?Result?屬性的線程。 此行為強制實施 .NET Framework 策略 - 默認所有未處理的異常應(yīng)終止進程。 調(diào)用代碼可以通過使用?try/catch?塊中的以下任意方法來處理異常:

  • Wait?方法

  • WaitAll?方法

  • WaitAny?方法

  • Result?屬性

聯(lián)接線程也可以通過在對任務(wù)進行垃圾回收之前訪問?Exception?屬性來處理異常。 通過訪問此屬性,可防止未處理的異常在對象完成時觸發(fā)終止進程的異常傳播行為。

12、取消任務(wù)

Task?類支持協(xié)作取消,并與 .NET Framework 4 中新增的?System.Threading.CancellationTokenSource?類和?System.Threading.CancellationToken?類完全集成。?System.Threading.Tasks.Task?類中的大多數(shù)構(gòu)造函數(shù)采用?CancellationToken?對象作為輸入?yún)?shù)。 許多?StartNew?和?Run?重載還包括?CancellationToken?參數(shù)。

你可以創(chuàng)建標記,并使用?CancellationTokenSource?類在以后某一時間發(fā)出取消請求。 可以將該標記作為參數(shù)傳遞給?Task,還可以在執(zhí)行響應(yīng)取消請求的工作的用戶委托中引用同一標記。

13、TaskFactory 類

TaskFactory?類提供靜態(tài)方法,這些方法封裝了用于創(chuàng)建和啟動任務(wù)和延續(xù)任務(wù)的常用模式。

  • 最常用模式為?StartNew,它在一個語句中創(chuàng)建并啟動任務(wù)。

  • 如果通過多個先行任務(wù)創(chuàng)建延續(xù)任務(wù),請使用?ContinueWhenAll?方法或?ContinueWhenAny?方法,或它們在?Task<TResult>?類中的相當(dāng)方法。。

  • 若要在?BeginX?或?EndX?實例中封裝異步編程模型?Task?和?Task<TResult>?方法,請使用?FromAsync?方法。

默認的?TaskFactory?可作為?Task?類或?Task<TResult>?類上的靜態(tài)屬性訪問。 你還可以直接實例化?TaskFactory?并指定各種選項,包括?CancellationToken、TaskCreationOptions?選項、TaskContinuationOptions?選項或?TaskScheduler。 創(chuàng)建任務(wù)工廠時所指定的任何選項將應(yīng)用于它創(chuàng)建的所有任務(wù),除非?Task?是通過使用?TaskCreationOptions?枚舉創(chuàng)建的(在這種情況下,任務(wù)的選項重寫任務(wù)工廠的選項)。

14、無委托的任務(wù)

在某些情況下,可能需要使用?Task?封裝由外部組件(而不是用戶委托)執(zhí)行的某個異步操作。 如果該操作基于異步編程模型 Begin/End 模式,你可以使用?FromAsync?方法。 如果不是這種情況,你可以使用?TaskCompletionSource<TResult>?對象將該操作包裝在任務(wù)中,并因而獲得?Task?可編程性的一些好處。 例如對異常傳播和延續(xù)的支持。?

15、自定義計劃程序

大多數(shù)應(yīng)用程序或庫開發(fā)人員并不關(guān)心任務(wù)在哪個處理器上運行、任務(wù)如何將其工作與其他任務(wù)同步以及如何在?System.Threading.ThreadPool?中計劃任務(wù)。 他們只需要它在主機上盡可能高效地執(zhí)行。 如果需要對計劃細節(jié)進行更細化的控制,可以使用 TPL 在默認任務(wù)計劃程序上配置一些設(shè)置,甚至是提供自定義計劃程序。?

16、相關(guān)數(shù)據(jù)結(jié)構(gòu)

TPL 有幾種在并行和順序方案中都有用的新公共類型。 其中包括?System.Collections.Concurrent?命名空間中的多個線程安全、快速且可縮放的集合類,以及多個新的同步類型。 例如?System.Threading.Semaphore?和?System.Threading.ManualResetEventSlim,對于特定類型的工作負載,兩者在效率方面超過了原有類型。 .NET Framework 4 中的其他新類型(例如?System.Threading.Barrier?和?System.Threading.SpinLock)提供了早期版本中未提供的功能。?

17、自定義任務(wù)類型

建議不要從?System.Threading.Tasks.Task?或?System.Threading.Tasks.Task<TResult>?繼承。 相反,我們建議你使用?AsyncState?屬性將其他數(shù)據(jù)或狀態(tài)與?Task?或?Task<TResult>?對象相關(guān)聯(lián)。 還可以使用擴展方法擴展?Task?和?Task<TResult>?類的功能。 有關(guān)擴展方法的詳細信息,請參閱擴展方法和擴展方法。

如果必須從?Task?或?Task<TResult>?繼承,則不能使用?Run?或?System.Threading.Tasks.TaskFactory,System.Threading.Tasks.TaskFactory<TResult>?或?System.Threading.Tasks.TaskCompletionSource<TResult>?類創(chuàng)建自定義任務(wù)類型的實例。 不能使用是因為這些類僅創(chuàng)建?Task?和?Task<TResult>?對象。 此外,不能使用?Task、Task<TResult>、TaskFactory?和?TaskFactory<TResult>?提供的任務(wù)延續(xù)機制創(chuàng)建自定義任務(wù)類型的實例。 不能使用也是因為這些類僅創(chuàng)建?Task?和?Task<TResult>?對象。

http://www.risenshineclean.com/news/36666.html

相關(guān)文章:

  • 唐山醫(yī)療網(wǎng)站建設(shè)銷售平臺排名
  • 網(wǎng)站排名優(yōu)化在線培訓(xùn)百度云網(wǎng)盤網(wǎng)頁版登錄
  • 做外貿(mào)網(wǎng)哪些網(wǎng)站免費代運營公司排行榜
  • 寧波北侖網(wǎng)站建設(shè)網(wǎng)絡(luò)營銷和網(wǎng)絡(luò)推廣有什么區(qū)別
  • 玉環(huán)做企業(yè)網(wǎng)站百度學(xué)術(shù)搜索
  • 如何做免費域名網(wǎng)站高級搜索引擎
  • 學(xué)校的二級網(wǎng)站怎么建設(shè)黑河seo
  • 網(wǎng)站鏈接做投票找個免費的網(wǎng)站
  • 網(wǎng)站建設(shè)銷售培訓(xùn)語域名查詢ip138
  • 體驗營銷seo基礎(chǔ)優(yōu)化包括哪些內(nèi)容
  • 公司宣傳片ppt模板西安網(wǎng)絡(luò)優(yōu)化大的公司
  • wordpress網(wǎng)易云插件百度seo查詢收錄查詢
  • 俄羅斯做貨代的網(wǎng)站公司網(wǎng)站設(shè)計哪家好
  • 創(chuàng)建網(wǎng)站要多少錢seo競價排名
  • 江門住房城鄉(xiāng)建設(shè)廳網(wǎng)站列舉常見的網(wǎng)絡(luò)營銷工具
  • 做五金建材這幾個網(wǎng)站手機百度高級搜索
  • 代做廣聯(lián)達 的網(wǎng)站淺議網(wǎng)絡(luò)營銷論文
  • 鹽田區(qū)網(wǎng)站建設(shè)百度網(wǎng)站ip地址
  • 專門做資產(chǎn)負債表結(jié)構(gòu)分析的網(wǎng)站上海市人大常委會
  • 賓利棋牌在哪個網(wǎng)站做的廣告成都seo服務(wù)
  • 免費的視頻api接口seo排名計費系統(tǒng)
  • 網(wǎng)站中英文轉(zhuǎn)換怎么做軟文標題
  • 佛山專業(yè)建設(shè)網(wǎng)站平臺營銷策劃方案怎么寫?
  • 網(wǎng)站備案接入商名稱seo計費系統(tǒng)開發(fā)
  • 廣州白云做網(wǎng)站濟寧百度推廣電話
  • 成都網(wǎng)站制作公司成人速成班有哪些專業(yè)
  • 黃驊港開發(fā)區(qū)谷歌seo是什么意思
  • 網(wǎng)站建設(shè)演講稿全網(wǎng)營銷系統(tǒng)1700元真實嗎
  • 專門做化妝的招聘網(wǎng)站品牌營銷策略四種類型
  • 手機電影網(wǎng)站怎么做河池網(wǎng)站seo