gpt4 book ai didi

c# - 运行多个线程,在另一个完成时启动新线程

转载 作者:行者123 更新时间:2023-11-30 22:47:30 25 4
gpt4 key购买 nike

我有一个应用程序有很多案例。每个案例都有许多多页 tif 文件。我需要将 tf 文件转换为 pdf 文件。由于有这么多文件,我想我可以线程转换过程。我目前将过程限制为一次转换十次(即十个踏板)。当一个转换完成时,另一个应该开始。

这是我当前使用的设置。

private void ConvertFiles()
{
List<AutoResetEvent> semaphores = new List<AutoResetEvet>();
foreach(String fileName in filesToConvert)
{
String file = fileName;

if(semaphores.Count >= 10)
{
WaitHandle.WaitAny(semaphores.ToArray());
}


AutoResetEvent semaphore = new AutoResetEvent(false);
semaphores.Add(semaphore);

ThreadPool.QueueUserWorkItem(
delegate
{
Convert(file);
semaphore.Set();
semaphores.Remove(semaphore);
}, null);
}

if(semaphores.Count > 0)
{
WaitHandle.WaitAll(semaphores.ToArray());
}
}

使用此方法有时会导致异常,指出 WaitHandle.WaitAll() 或 WaitHandle.WaitAny() 数组参数的长度不得超过 65。我在这种方法中做错了什么,我该如何纠正它?

最佳答案

你写的有一些问题。

第一,它不是线程安全的。您有多个线程添加、删除和等待 AutoResetEvents 数组。 List 的各个元素可以在单独的线程上访问,但是任何添加、删除或检查所有元素(如 WaitAny 调用)的操作都需要在锁内进行。

第二,不能保证您的代码一次只能处理 10 个文件。检查列表大小和添加新项目之间的代码是开放的,供多个线程通过。

第三,在 QueueUserWorkItem 中启动的线程有可能转换同一个文件。如果不在循环内捕获文件名,转换文件的线程将在执行时使用文件名中的任何值,而不是调用 QueueUserWorkItem 时文件名中的任何值。

这篇代码项目文章应该为您指明正确的方向以完成您正在尝试做的事情:http://www.codeproject.com/KB/threads/SchedulingEngine.aspx

编辑:

var semaphores = new List<AutoResetEvent>();
foreach (String fileName in filesToConvert)
{
String file = fileName;
AutoResetEvent[] array;
lock (semaphores)
{
array = semaphores.ToArray();
}
if (array.Count() >= 10)
{
WaitHandle.WaitAny(array);
}

var semaphore = new AutoResetEvent(false);
lock (semaphores)
{
semaphores.Add(semaphore);
}
ThreadPool.QueueUserWorkItem(
delegate
{
Convert(file);
lock (semaphores)
{
semaphores.Remove(semaphore);
}
semaphore.Set();
}, null);
}

就我个人而言,我不认为我会这样做...但是,使用您拥有的代码,这应该可行。

关于c# - 运行多个线程,在另一个完成时启动新线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2196945/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com