WaitHandle.WaitAll 上的 NotSupportedException

发布于 2024-09-24 14:10:29 字数 1053 浏览 3 评论 0原文

我正在尝试执行以下代码。该代码尝试并行下载和保存图像。我传递了要下载的图像列表。我用 C# 3.0 编写了此代码,并使用 .NET Framework 4(VS.NET Express 版本)对其进行了编译。每次我尝试运行程序时,WaitAll 操作都会导致 NotSupportedException(不支持 STA 线程上多个句柄的 WaitAllll)。我尝试删除 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");
}

您能让我了解我遇到的问题是什么吗?

谢谢

I am trying to execute the following code. The code tries to parallely download and save images. I pass a list of images to be downloaded. I wrote this in C# 3.0 and compiled it using .NET Framework 4 (VS.NET express edition). The WaitAll operation is resulting in a NotSupportedException (WaitAlll for multiple handles on a STA thread is not supported) everytime I try to run my program. I tried removing SetMaxThreads, but that didn't do any difference.

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");
}

Can you please let me understand what is the issue I am running into?

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

虚拟世界 2024-10-01 14:10:30

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

Did you mark one of the methods with [STAThread] attribute?

无名指的心愿 2024-10-01 14:10:30

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

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

Have you tried setting the apartment state for the thread?

thread.SetApartmentState (System.Threading.Apartmentstate.MTA );
生死何惧 2024-10-01 14:10:29

我建议不要使用多个 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"); 
} 

I advise against using multiple WaitHandle instances to wait for completion. Use the CountdownEvent class instead. It results in more elegant and scalable code. Plus, the WaitHandle.WaitAll method only supports up to 64 handles and cannot be called on an STA thread. By refactoring your code to use the canonical pattern I came up with this.

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"); 
} 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文