如何:使用 Parallel.Invoke 執行平行作業
這個範例示範如何使用工作平行程式庫中的 Invoke 平行處理作業。 我們會對共用資料來源執行三項作業。 由於可以直接平行執行這些作業,因此這些作業都不會修改來源。
注意
本文件使用 Lambda 運算式來定義 TPL 中的委派。 如果您不熟悉 C# 或 Visual Basic 中的 Lambda 運算式,請參閱 PLINQ 和 TPL 中的 Lambda 運算式。
範例
namespace ParallelTasks
{
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
class ParallelInvoke
{
static void Main()
{
// Retrieve Goncharov's "Oblomov" from Gutenberg.org.
string[] words = CreateWordArray(@"http://www.gutenberg.org/files/54700/54700-0.txt");
#region ParallelTasks
// Perform three tasks in parallel on the source array
Parallel.Invoke(
() =>
{
Console.WriteLine("Begin first task...");
GetLongestWord(words);
}, // close first Action
() =>
{
Console.WriteLine("Begin second task...");
GetMostCommonWords(words);
}, //close second Action
() =>
{
Console.WriteLine("Begin third task...");
GetCountForWord(words, "sleep");
} //close third Action
); //close parallel.invoke
Console.WriteLine("Returned from Parallel.Invoke");
#endregion
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
#region HelperMethods
private static void GetCountForWord(string[] words, string term)
{
var findWord = from word in words
where word.ToUpper().Contains(term.ToUpper())
select word;
Console.WriteLine($@"Task 3 -- The word ""{term}"" occurs {findWord.Count()} times.");
}
private static void GetMostCommonWords(string[] words)
{
var frequencyOrder = from word in words
where word.Length > 6
group word by word into g
orderby g.Count() descending
select g.Key;
var commonWords = frequencyOrder.Take(10);
StringBuilder sb = new StringBuilder();
sb.AppendLine("Task 2 -- The most common words are:");
foreach (var v in commonWords)
{
sb.AppendLine(" " + v);
}
Console.WriteLine(sb.ToString());
}
private static string GetLongestWord(string[] words)
{
var longestWord = (from w in words
orderby w.Length descending
select w).First();
Console.WriteLine($"Task 1 -- The longest word is {longestWord}.");
return longestWord;
}
// An http request performed synchronously for simplicity.
static string[] CreateWordArray(string uri)
{
Console.WriteLine($"Retrieving from {uri}");
// Download a web page the easy way.
string s = new WebClient().DownloadString(uri);
// Separate string into an array of words, removing some common punctuation.
return s.Split(
new char[] { ' ', '\u000A', ',', '.', ';', ':', '-', '_', '/' },
StringSplitOptions.RemoveEmptyEntries);
}
#endregion
}
}
// The example displays output like the following:
// Retrieving from http://www.gutenberg.org/files/54700/54700-0.txt
// Begin first task...
// Begin second task...
// Begin third task...
// Task 2 -- The most common words are:
// Oblomov
// himself
// Schtoltz
// Gutenberg
// Project
// another
// thought
// Oblomov's
// nothing
// replied
//
// Task 1 -- The longest word is incomprehensible.
// Task 3 -- The word "sleep" occurs 57 times.
// Returned from Parallel.Invoke
// Press any key to exit
Imports System.Net
Imports System.Threading.Tasks
Module ParallelTasks
Sub Main()
' Retrieve Goncharov's "Oblomov" from Gutenberg.org.
Dim words As String() = CreateWordArray("http://www.gutenberg.org/files/54700/54700-0.txt")
'#Region "ParallelTasks"
' Perform three tasks in parallel on the source array
Parallel.Invoke(Sub()
Console.WriteLine("Begin first task...")
GetLongestWord(words)
' close first Action
End Sub,
Sub()
Console.WriteLine("Begin second task...")
GetMostCommonWords(words)
'close second Action
End Sub,
Sub()
Console.WriteLine("Begin third task...")
GetCountForWord(words, "sleep")
'close third Action
End Sub)
'close parallel.invoke
Console.WriteLine("Returned from Parallel.Invoke")
'#End Region
Console.WriteLine("Press any key to exit")
Console.ReadKey()
End Sub
#Region "HelperMethods"
Sub GetCountForWord(ByVal words As String(), ByVal term As String)
Dim findWord = From word In words
Where word.ToUpper().Contains(term.ToUpper())
Select word
Console.WriteLine($"Task 3 -- The word ""{term}"" occurs {findWord.Count()} times.")
End Sub
Sub GetMostCommonWords(ByVal words As String())
Dim frequencyOrder = From word In words
Where word.Length > 6
Group By word
Into wordGroup = Group, Count()
Order By wordGroup.Count() Descending
Select wordGroup
Dim commonWords = From grp In frequencyOrder
Select grp
Take (10)
Dim s As String
s = "Task 2 -- The most common words are:" & vbCrLf
For Each v In commonWords
s = s & v(0) & vbCrLf
Next
Console.WriteLine(s)
End Sub
Function GetLongestWord(ByVal words As String()) As String
Dim longestWord = (From w In words
Order By w.Length Descending
Select w).First()
Console.WriteLine($"Task 1 -- The longest word is {longestWord}.")
Return longestWord
End Function
' An http request performed synchronously for simplicity.
Function CreateWordArray(ByVal uri As String) As String()
Console.WriteLine($"Retrieving from {uri}")
' Download a web page the easy way.
Dim s As String = New WebClient().DownloadString(uri)
' Separate string into an array of words, removing some common punctuation.
Return s.Split(New Char() {" "c, ControlChars.Lf, ","c, "."c, ";"c, ":"c,
"-"c, "_"c, "/"c}, StringSplitOptions.RemoveEmptyEntries)
End Function
#End Region
End Module
' The example displays output like the following:
' Retrieving from http://www.gutenberg.org/files/54700/54700-0.txt
' Begin first task...
' Begin second task...
' Begin third task...
' Task 2 -- The most common words are:
' Oblomov
' himself
' Schtoltz
' Gutenberg
' Project
' another
' thought
' Oblomov's
' nothing
' replied
'
' Task 1 -- The longest word is incomprehensible.
' Task 3 -- The word "sleep" occurs 57 times.
' Returned from Parallel.Invoke
' Press any key to exit
使用 Invoke 時,您只需指出要並行執行的動作即可,執行階段會處理所有執行緒排程詳細資料,包括自動根據主機電腦的核心數進行調整。
這個範例會平行處理作業,而不是資料。 除了前述方法以外,您也可以使用 PLINQ 來平行處理 LINQ 查詢,並依序執行查詢。 或者,您可以使用 PLINQ 來平行處理資料。 另一種方式是同時平行處理查詢和工作。 雖然產生的額外負荷可能會使處理器數目相對較少的主機電腦效能減低,但會適用在具有較多處理器的電腦上。
編譯程式碼
將整個範例複製並貼到 Microsoft Visual Studio 專案中,然後按 F5 鍵。