System.Threading.Parallel 的用法

System.Threading.Parallel 提供了几种实用的循环并行处理方法,让我们可以用非常简便的代码完成并发处理。

1. For
var datas = new[] { "a", "b", "c" };

Parallel.For(0, datas.Length, i =>
{
   var s = datas[i];
   Console.WriteLine(">>> Thread:{0}, {1}", Thread.CurrentThread.ManagedThreadId, s);
});

输出:
>>> Thread:3, a
>>> Thread:7, b
>>> Thread:5, c

我们还可以像 for(;; i += 2) 那样指定循环递增幅度。
var datas = new[] { "a", "b", "c", "d", "e" };

Parallel.For(0, datas.Length, 2, i =>
{
   var s = datas[i];
   Console.WriteLine(">>> Thread:{0}, {1}", Thread.CurrentThread.ManagedThreadId, s);
});

for (int i = 0; i < datas.Length; i += 2)
{
   Console.WriteLine(datas[i]);
}

输出:
>>> Thread:3, a
>>> Thread:7, e
>>> Thread:4, c
a
c
e

For() 还提供了更多更复杂的重载,包括提供 init、finally、state 等操作。

比如,我们可以通过调用 ParallelState.Stop() 来停止后续处理。
var datas = new[] { "a", "b", "c", "d", "e" };

Parallel.For(0, datas.Length, (i, state) =>
   {
     state.Stop();

     var s = datas[i];
     Console.WriteLine(">>> Thread:{0}, {1}",
       Thread.CurrentThread.ManagedThreadId, s);
   });

输出:
>>> Thread:3, a
>>> Thread:7, b
>>> Thread:5, c

还可以像下面这样,添加初始化、结束处理委托,并传递额外的参数给并行代码。
var datas = new[] { "a", "b" };

Parallel.For<int>(0, datas.Length,
   () =>
   {
     Console.WriteLine("Init {0}...", Thread.CurrentThread.ManagedThreadId);
     return 123;
   },
   (i, state) =>
   {
     state.Stop();

     var s = datas[i];
     Console.WriteLine(">>> Thread:{0}, {1}, {2}",
       Thread.CurrentThread.ManagedThreadId, s, state.ThreadLocalState);
   },
   (x) =>
   {
     Console.WriteLine("Finally {0}, {1}...", Thread.CurrentThread.ManagedThreadId, x);
   });

输出:
Init 3...
Init 5...
>>> Thread:3, a, 123
>>> Thread:5, b, 123
Finally 3, 123...
Finally 5, 123...

2. Foreach

ForEach() 和 For() 的用法非常类似。
var datas = new[] { "a", "b", "c", "d", "e" };

Parallel.ForEach(datas, s =>
{
   Console.WriteLine(">>> thread:{0}, {1}",
     Thread.CurrentThread.ManagedThreadId, s);
});

输出:
>>> thread:3, a
>>> thread:6, b
>>> thread:5, c
>>> thread:6, e
>>> thread:7, d

作者善解人意,同样提供了多种重载,包括获取索引位置以及并发状态管理等等。
var datas = new[] { "a", "b", "c", "d", "e" };

Parallel.ForEach(datas, (s, i, state) =>
{
   Console.WriteLine(">>> thread:{0}, index:{1}, {2}",
     Thread.CurrentThread.ManagedThreadId, i, s);
});

输出:
>>> thread:3, index:0, a
>>> thread:7, index:3, d
>>> thread:6, index:2, c
>>> thread:7, index:4, e
>>> thread:5, index:1, b

3. Invoke

Invoke 针对的是 "并发逻辑" 而非 "并发数据"。当然,我们也可以将 "并发逻辑" 打包成数据集合(Delegate[]) 提交给 For/Foreach 执行,只不过 Invoke 更简便一些。
Parallel.Invoke(new Action[]
{
   () => Console.WriteLine(">>> thread:{0}, {1}", Thread.CurrentThread.ManagedThreadId, 1),
   () => Console.WriteLine(">>> thread:{0}, {1}", Thread.CurrentThread.ManagedThreadId, "a"),
   () => Console.WriteLine(">>> thread:{0}, {1}", Thread.CurrentThread.ManagedThreadId, typeof(object)),
});

输出:
>>> thread:3, 1
>>> thread:5, System.Object
>>> thread:4, a

改用 TPL / Invoke 写蜘蛛(Spider/Crawler)抓取代码,可以大大简化代码样式,少了许多线程管理调度

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值