C#多线程问题

4
我的现有c#应用程序更新一个SharePoint网站集合。现在我被要求让我的c#应用程序更新不是1个而是15个网站集合。串行运行将花费太长时间,因此线程会是一个好的解决方案。
然而,我不能一次打开15个线程,我想要一个可配置的值,它将是同时运行的最大线程数。
我期望的是:
定义Max_Threads变量...
在线程池中分配一组任务(函数),在这种情况下为15个任务或函数调用。
然后线程池执行每个线程,但受限于打开的线程数量(例如5个)。
一旦一个线程完成,线程池就重用该线程来完成另一个工作项,直到所有工作完成。
所以我的问题是:所有这些都内置在.net线程中吗?还是我必须手动创建线程管理代码?
编辑: 这是一个框架3.5项目,很抱歉之前没有提及。
5个回答

3

只需使用任务,不必考虑线程数量。TPL 会为您完成所有这些。


3
这本书《C# in a Nutshell, 4.0》(作者:Albahari & Albahari)提供了一个简洁的示例,同时调用许多“Web客户端”并下载信息。它使用PLINQ,在一行或几行代码中完成。PLINQ库处理线程的创建等等。如果你看一下,它不会产生太多线程,尽管你可以强制限制同时执行的线程数的最大值。同样,你可以使用Parallel.Foreach()并使用“ParallelOptions”参数来限制线程数量。
好处是你永远不必自己创建线程-它是自动的。而且它做了很好的负载均衡。
一个好的教程是http://www.albahari.com/threading/ - 看看第5部分的并行编程的许多使用PLINQ和Parallel.Foreach的示例。
此外,Wagner的Effective C#(4.0)也有类似的示例。

2

1
考虑使用适用于.NET 3.5的Reactive Extensions回溯版本。这将允许您使用任务并行库(TPL)。如果无法选用此选项,请继续阅读。
我会一次性将整个站点集合扔到ThreadPool中,看看运行情况如何,然后再尝试限制工作项。
如果你确实需要限制ThreadPool中同时运行的工作项数量,那么可以使用信号量对其进行限制。但是,请注意不要阻塞ThreadPool线程,因为这被认为是不良实践。相反,请阻塞排队线程。
int pending = sites.Count;
var finished = new ManualResetEvent(false);
var semaphore = new Semaphore(5, 5);
foreach (string site in sites)
{
  semaphore.WaitOne();
  ThreadPool.QueueUserWorkItem(
    (state) =>
    {
      try
      {
        // Process your work item here.
      }
      finally
      {
        semaphore.Release();
        if (Interlocked.Decrement(ref pending) == 0)
        {
          finished.Set(); // This is the last work item.
        }
      }
    }, null);
}
finished.WaitOne(); // Wait for all work items to complete.

1

使用 TPL,它将依次使用 .NET 线程池(默认情况下)。它应该会自动调整到运行环境:

从 .NET Framework 4 版本开始,进程的线程池默认大小取决于多个因素,例如虚拟地址空间的大小。

你只需要在非常有限的 情况下 进行自己的线程管理:

  • 你需要一个前台线程。

  • 您需要为线程设置特定的优先级。

  • 您有一些任务会导致线程长时间阻塞。线程池具有最大数量的线程,因此大量阻止的线程可能会防止任务启动。

  • 您需要将线程放入单线程公寓中。所有的线程池线程都在多线程公寓中。

  • 您需要将稳定的身份与线程相关联,或者将线程专用于某个任务。

如果您使用.NET 3.5,则应查看本文,该文章解释了如何直接使用线程池实现部分TPL功能:“TPL”是否真正使您能够做到无法在.NET 2.0中使用“ThreadPool”进行的任何操作?


+1 作为抵消负分的加分。我并没有看到任何可以证明这个回答得到负数评分的理由。 - Brian Gideon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接