Paralle类的主要方法包括For,ForEach,Invoke,运行这几个方法时,会阻塞调用线程,知道所有Action执行完毕后继续执行后续语句。如果在UI线程中使用Parallel方法,则可能会造成UI阻塞,因此,可以选择在次线程中调用。
private void btn_click(object sender,EventArgs e)
{
Task.Factory.StartNew(()=>
{
UseParallelMethod();//在这个方法中使用到Parallel
});
//Do Other Work ...
Other Work Code here
}
private void UseParallelMethod()
{
Parallel.For(...);
// Parallel.ForEach(...);
// Parallel.Invoke(...);
//other work
Other Work code
}
(1)ParallelLoopResult For (int fromInclusive, int toExclusive, Action<int> body) 执行 for
循环,其中可能会并行运行迭代。
public static void Main()
{
ParallelLoopResult result = Parallel.For(0, 100, ctr => { Random rnd = new Random(ctr * 100000);
Byte[] bytes = new Byte[100];
rnd.NextBytes(bytes);
int sum = 0;
foreach(var byt in bytes)
sum += byt;
Console.WriteLine("Iteration {0,2}: {1:N0}", ctr, sum);
});
Console.WriteLine("Result: {0}", result.IsCompleted ? "Completed Normally" :
String.Format("Completed to {0}", result.LowestBreakIteration));
}
(2)ParallelLoopResult ForEach<TSource> (IEnumerable<TSource> source, Action<TSource> body) 执行 foreach
操作,其中在 IEnumerable 上可能会并行运行迭代。
public static void Main()
{
Task<String> task = ReadCharacters(@".\CallOfTheWild.txt");
String text = task.Result;
int nVowels = 0;
int nNonWhiteSpace = 0;
Object obj = new Object();
ParallelLoopResult result = Parallel.ForEach(text,
(ch) => {
Char uCh = Char.ToUpper(ch);
if ("AEIOUY".IndexOf(uCh) >= 0) {
lock (obj) {
nVowels++;
}
}
if (! Char.IsWhiteSpace(uCh)) {
lock (obj) {
nNonWhiteSpace++;
}
}
} );
Console.WriteLine("Total characters: {0,10:N0}", text.Length);
Console.WriteLine("Total vowels: {0,10:N0}", nVowels);
Console.WriteLine("Total non-white-space: {0,10:N0}", nNonWhiteSpace);
}
private static async Task<String> ReadCharacters(String fn)
{
String text;
using (StreamReader sr = new StreamReader(fn)) {
text = await sr.ReadToEndAsync();
}
return text;
}
(3)void Invoke (params Action[] actions) 尽可能并行执行提供的每个操作。
static void Main()
{
try
{
Parallel.Invoke(
BasicAction, // Param #0 - static method
() => // Param #1 - lambda expression
{
Console.WriteLine("Method=beta, Thread={0}", Thread.CurrentThread.ManagedThreadId);
},
delegate() // Param #2 - in-line delegate
{
Console.WriteLine("Method=gamma, Thread={0}", Thread.CurrentThread.ManagedThreadId);
}
);
}
// No exception is expected in this example, but if one is still thrown from a task,
// it will be wrapped in AggregateException and propagated to the main thread.
catch (AggregateException e)
{
Console.WriteLine("An action has thrown an exception. THIS WAS UNEXPECTED.\n{0}", e.InnerException.ToString());
}
}
static void BasicAction()
{
Console.WriteLine("Method=alpha, Thread={0}", Thread.CurrentThread.ManagedThreadId);
}
如果在并行的方法中(很多情况是Action中),需要使用UI元素,则不能直接使用元素,而应该将其通知到UI线程中去处理。在
WPF中,使用this.Dispatcher.Invoke(),在WinForm中使用this.Invoke()。