WaitHandle.WaitAll上的NotSupportedException

时间:2010-09-24 05:45:40

标签: c# multithreading threadpool

我正在尝试执行以下代码。代码尝试并行下载和保存图像。我传递了要下载的图像列表。我在C#3.0中编写了这个,并使用.NET Framework 4(VS.NET express edition)进行编译。每次我尝试运行我的程序时,WaitAll操作都会导致 NotSupportedException(不支持STA线程上的多个句柄的WaitAlll)。我尝试删除SetMaxThreads,但这没有任何区别。

public static void SpawnThreads(List<string> imageList){
    imageList = new List<string>(imageList);
    ManualResetEvent[] doneEvents = new ManualResetEvent[imageList.Count];
    PicDownloader[] picDownloaders = new PicDownloader[imageList.Count];
    ThreadPool.SetMaxThreads(MaxThreadCount, MaxThreadCount);
    for (int i = 0; i < imageList.Count; i++) {
        doneEvents[i] = new ManualResetEvent(false);
        PicDownloader p = new PicDownloader(imageList[i], doneEvents[i]);
        picDownloaders[i] = p;
        ThreadPool.QueueUserWorkItem(p.DoAction);
    }
    // The following line is resulting in "NotSupportedException"     
    WaitHandle.WaitAll(doneEvents);
    Console.WriteLine("All pics downloaded");
}

请您理解我遇到的问题是什么?

谢谢

3 个答案:

答案 0 :(得分:7)

我建议不要使用多个WaitHandle个实例来等待完成。请改用CountdownEvent课程。它产生更优雅和可扩展的代码。另外,WaitHandle.WaitAll方法最多只支持64个句柄,并且无法在STA线程上调用。通过重构代码以使用规范模式,我想出了这个。

public static void SpawnThreads(List<string> imageList)
{ 
  imageList = new List<string>(imageList); 
  var finished = new CountdownEvent(1);
  var picDownloaders = new PicDownloader[imageList.Count]; 
  ThreadPool.SetMaxThreads(MaxThreadCount, MaxThreadCount); 
  for (int i = 0; i < imageList.Count; i++) 
  { 
    finished.AddCount();    
    PicDownloader p = new PicDownloader(imageList[i]); 
    picDownloaders[i] = p; 
    ThreadPool.QueueUserWorkItem(
      (state) =>
      {
        try
        {
          p.DoAction
        }
        finally
        {
          finished.Signal();
        }
      });
  } 
  finished.Signal();
  finished.Wait();
  Console.WriteLine("All pics downloaded"); 
} 

答案 1 :(得分:5)

您是否使用[STAThread]属性标记了其中一种方法?

答案 2 :(得分:0)

您是否尝试过设置线程的公寓状态?

thread.SetApartmentState (System.Threading.Apartmentstate.MTA );