目录
三、Invoke(ParallelOptions, Action[])
尽可能并行执行提供的每个操作。使用Parallel.Invoke 方法。
最简单,最简洁的将串行的代码并行化。
一、重载
Invoke(Action[]) | 尽可能并行执行提供的每个操作。 |
Invoke(ParallelOptions, Action[]) | 执行所提供的每个操作,而且尽可能并行运行,除非用户取消了操作。 |
二、Invoke(Action[])
尽可能并行执行提供的每个操作。
1.定义
public static void Invoke (params Action[] actions);
参数
actions Action[]
要执行的 Action 数组。
例外
ArgumentNullException
actions 参数为 null。
AggregateException
当 actions 数组中的任何操作引发异常时引发的异常。
ArgumentException
actions数组包含 null 个元素。
2.示例
Invoke方法经常与其他方法、匿名委托和 lambda 表达式配合使用,实现并行方法的线程同步。
// Parallel.Invoke()方法
// 将 Invoke 方法与其他方法、匿名委托和 lambda 表达式结合使用。
namespace ConsoleApp15
{
class ParallelInvokeDemo
{
/// <summary>
/// 执行每个任务的线程可能不同。
/// 不同的执行中线程分配可能不同。
/// 任务可能按任何顺序执行。
/// </summary>
static void Main()
{
try
{
Parallel.Invoke(
BasicAction, // Param #0 - static method
() => // Param #1 - lambda expression
{
Console.WriteLine("Method=beta, Thread={0}", Environment.CurrentManagedThreadId);
},
delegate () // Param #2 - in-line delegate
{
Console.WriteLine("Method=gamma, Thread={0}", Environment.CurrentManagedThreadId);
}
);
}
// 一般不会出现异常,但如万一抛出异常,
// 它将被包装在 AggregateException 中并传播到主线程。
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}", Environment.CurrentManagedThreadId);
}
}
}
// 运行结果:
/*
Method=beta, Thread=4
Method=alpha, Thread=1
Method=gamma, Thread=10
*/
三、Invoke(ParallelOptions, Action[])
执行所提供的每个操作,而且尽可能并行运行,除非用户取消了操作。
1.定义
public static void Invoke (System.Threading.Tasks.ParallelOptions parallelOptions, params Action[] actions);
参数
parallelOptions ParallelOptions
一个对象,用于配置此操作的行为。
actions Action[]
要执行的操作数组。
例外
OperationCanceledException
CancellationToken 处于 parallelOptions 设置。
ArgumentNullException
actions 参数为 null。
或 - parallelOptions 参数为 null。
AggregateException
当 actions 数组中的任何操作引发异常时引发的异常。
ArgumentException
actions数组包含 null 个元素。
ObjectDisposedException
在 parallelOptions 中与 CancellationTokenSource 关联的 CancellationToken 已被释放。
注解
此方法可用于执行一组可能并行的操作。 使用结构传入 ParallelOptions 的取消令牌使调用方能够取消整个操作。
2. 常用的使用方法
Parallel.Invoke(
() => { },
() => { },
() => { }
);
(1)示例1
- 一个任务是可以分解成多个任务,采用分而治之的思想;
- 尽可能的避免子任务之间的依赖性,因为子任务是并行执行,所以就没有谁一定在前,谁一定在后的规定了;
- 主线程必须等Invoke中的所有方法执行完成后返回才继续向下执行。暗示以后设计并行的时候,要考虑每个Task任务尽可能差不多,如果相差很大,比如一个时间非常长,其他都比较短,这样一个线程可能会影响整个任务的性能。这点非常重要;
- 没有固定的顺序,每个Task可能是不同的线程去执行,也可能是相同的;
namespace ConsoleApp16
{
internal class Program
{
private static void Main(string[] args)
{
ArgumentNullException.ThrowIfNull(args);
ParallelMothed();
static void ParallelMothed()
{
Parallel.Invoke(Run1, Run2); //这里的Run1 Run2 都是方法。
}
}
static void Run1()
{
Console.WriteLine("我是任务一,我跑了3s");
Thread.Sleep(3000);
}
static void Run2()
{
Console.WriteLine("我是任务二,我跑了5s");
Thread.Sleep(5000);
}
}
}
//运行结果:
/*
我是任务二,我跑了5s
我是任务一,我跑了3s
*/
(2)示例2
如果调用的方法是有参数的,如何处理?同理,直接带上参数就可以,
Parallel.Invoke(() => Task1("task1"), () => Task2("task2"), () => Task3("task3"));
// Invoke带参数 调用
using System.Diagnostics;
namespace ConsoleApp17
{
class ParallelInvoke
{
public static void Main(string[] args)
{
ArgumentNullException.ThrowIfNull(args);
Stopwatch stopWatch = new();
Console.WriteLine("主线程:{0}线程ID : {1};开始", "Main", Environment.CurrentManagedThreadId);
stopWatch.Start();
Parallel.Invoke(
() => Task1("task1"),
() => Task2("task2"),
() => Task3("task3")
);
stopWatch.Stop();
Console.WriteLine("主线程:{0}线程ID : {1};结束,共用时{2}ms", "Main", Environment.CurrentManagedThreadId, stopWatch.ElapsedMilliseconds);
Console.ReadKey();
}
private static void Task1(string data)
{
Thread.Sleep(5000);
Console.WriteLine("任务名:{0}线程ID : {1}", data, Environment.CurrentManagedThreadId);
}
private static void Task2(string data)
{
Console.WriteLine("任务名:{0}线程ID : {1}", data, Environment.CurrentManagedThreadId);
}
private static void Task3(string data)
{
Console.WriteLine("任务名:{0}线程ID : {1}", data, Environment.CurrentManagedThreadId);
}
}
}
//运行结果:
/*
主线程:Main线程ID : 1;开始
任务名:task2线程ID : 4
任务名:task3线程ID : 7
任务名:task1线程ID : 1
主线程:Main线程ID : 1;结束,共用时5020ms
*/
(3)Stopwatch类
提供一组方法和属性,可用于准确地测量运行时间。
其中,Stopwatch.Start 方法和Stopwatch.Stop 方法详见本文作者写的其他文章,C# 用于准确地测量运行时间的Stopwatch中.Start 方法和Stopwatch.Stop 方法-CSDN博客 https://wenchm.blog.csdn.net/article/details/135735170