Я работаю с семафором и потоками, чтобы попытаться управлять загрузкой чанка для воксельной игры, над которой я работаю. Моя общая настройка: у меня есть задание администратора очередей, которое создает семафор и дочерние задания, которые его ожидают. Я следовал всем примерам, но не могу понять, почему, когда я вызываю WaitOne () для моего семафора в моих дочерних заданиях, код никогда не продолжается ни для одного потока, кроме основного.
CODE: Вот конструктор для задания администратора очередей:
/// <summary>
/// Create a new job, linked to the level
/// </summary>
/// <param name="level"></param>
protected QueueManagerJob(int maxChildJobsCount = 10) {
queue = new List<QueueObjectType>();
runningChildJobs = new Dictionary<QueueObjectType, IThreadedJob>();
childJobResourcePool = new Semaphore(maxChildJobsCount, maxChildJobsCount);
}
Это функция, которую задание администратора очередей запускает в своей очереди:
/// <summary>
/// The threaded function to run
/// </summary>
protected override void jobFunction() {
// This job will continue until all queue'd chunks are loaded
while (queue.Count > 0) {
queue.RemoveAll((queueObject) => {
// if the chunk is already being loaded by a job
if (runningChildJobs.ContainsKey(queueObject)) {
IThreadedJob chunkLoaderJob = runningChildJobs[queueObject];
// if it's done, remove it from the running jobs and remove it from the queue
if (chunkLoaderJob.isDone) {
runningChildJobs.Remove(queueObject);
return true;
}
// if it's not done yet, don't remove it
return false;
// if it's not being loaded yet by a job, and we have an open spot for a new job, start and add it
} else {
IThreadedJob chunkLoaderJob = getChildJob(queueObject);
runningChildJobs[queueObject] = chunkLoaderJob;
runningChildJobs[queueObject].start();
// don't remove the running job from the queue yet
return false;
}
});
}
}
Это большинство дочерних элементов. задание:
/// <summary>
/// Threaded function, serializes this chunks block data and removes it from the level
/// </summary>
protected override void jobFunction() {
// wait until we have a resouces, or the job is canceled.
if (parentResourcePool.WaitOne(-1, isCanceled)) {
doWork();
parentResourcePool.Release();
// if the job is canceled, abort after releasing the resource
} else {
abort();
}
}
}
и на этом он останавливается. Каждый поток останавливается на
if (parentResourcePool.WaitOne(-1, isCanceled)) {
и, похоже, не продолжается дальше. Все они в конечном итоге выглядят так в отладчике:
Также вот ссылка на мою базу ThreadedJobкласс, который расширяют оба этих класса: https://github.com/SuperMeip/MarchingCubesCSharp.A1/blob/master/Assets/Scripts/Jobs/ThreadedJob.cs
на всякий случай, если проблема может быть связана с этим.