如何:使用 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 键。