C#线程问题

时间:2011-09-26 17:31:42

标签: c# multithreading

我现有的c#app更新了一个sharepoint网站集。现在我的任务是让我的c#app更新不是1个,而是15个网站集。顺序运行需要很长时间,因此线程将是一个很好的解决方案。

但是我不能一次打开15个线程,我希望有一个可配置的值,它将是一次运行的最大线程数。

我期望的是:

  • 定义Max_Threads变量......
  • 在线程池中分配任务(函数)队列,在本例中为15个任务或函数调用。
  • 线程池然后执行每个线程,但是受到多少个开放线程(例如5个)的限制。
  • 线程完成后,线程池会重新使用该线程执行另一项工作,直到所有工作完成。

所以我的问题是:所有这些都构建成.net线程。或者我是否必须手动创建线程管理代码?

编辑:这是一个框架3.5项目,很抱歉之前没有提到这个。

5 个答案:

答案 0 :(得分:3)

只使用任务而不考虑线程数。 TPL将为您完成所有这些。

答案 1 :(得分:3)

Cuts in the Nutshell 4.0(由Albahari& Albahari撰写)给出了一个同时调用许多“Web客户端”和下载信息的简洁例子。它使用PLINQ,在一行左右的代码中。 PLINQ库处理线程的创建等。如果你看一下它,它不会产生太多线程,尽管你可以一次强制限制最大线程数。同样,您可以使用Parallel.Foreach()并使用“ParallelOptions”参数来限制线程数。

好消息是你永远不必自己创建线程 - 它是自动的。它在负载平衡方面做得很好。

一个好的教程是http://www.albahari.com/threading/ - 关于使用PLINQ和Parallel.Foreach的大量例子,请参阅并行编程的第5部分。

此外,Wagner关于Effective C#(4.0)的书也有类似的例子。

答案 2 :(得分:2)

您可以使用.NET 4.0附带的Parallel框架: http://msdn.microsoft.com/en-us/library/dd460693.aspx

答案 3 :(得分:1)

使用TPL,然后使用.NET thread pool(默认情况下)。它假设自动适应它运行的环境:

  

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

您只需要在非常有限的number of cases中执行自己的线程管理:

  
      
  • 您需要一个前台线程。

  •   
  • 您需要一个具有特定优先级的线程。

  •   
  • 您的任务导致线程长时间阻塞   时间。线程池有最大线程数,所以很大   被阻止的线程池线程数可能会阻止任务   开始。

  •   
  • 您需要将线程放入单线程单元中。所有   ThreadPool线程位于多线程单元中。

  •   
  • 您需要具有与该线程关联的稳定标识,或者   将线程专用于任务。

  •   

如果您使用.NET 3.5,您应该查看解释如何直接使用线程池实现某些TPL功能的文章:Does the TPL really enable you to do anything you couldn't do with ThreadPool in .NET 2.0?

答案 4 :(得分: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.