В последнее время я боролся с многопоточностью.У меня есть консольное приложение C #, которое обучает нейронные сети.Я создаю поток через задачу для каждой сети, которую я собираюсь тренировать.Я создал событие обновления статуса для своего класса тренера, на который подписывается родительский класс.В этом обработчике событий я обновляю массив состояний новым статусом этой модели.В этом доступе к массиву я вижу «тупиковый» тип поведения.Я понимаю, что это не каноническое определение тупика, но я не могу придумать лучшего термина для описания ситуации.Ниже мой код.Я сжал это столько, сколько смог.
Я ценю любую помощь.Спасибо
Родительский код
public class TrainingEngine
{
public enum UpdateStatus
{
Untrimmed = 0,
Trimmed,
Completed
}
private class TrainingStatus
{
public int Epoch { get; set; }
public UpdateStatus UpdateStatus { get; set; }
}
private static readonly object printLock = new object();
private ConcurrentDictionary<int, TrainingStatus> trainingStatus;
...other stuff...
private void UpdateEpochCompleted(TrainingStatus newStatus)
{
trainingStatus[newStatus.ThreadId] = newStatus;
PrintUpdate($"Model {newStatus.ThreadId + 1} completed epoch {newStatus.Epoch}.");
}
private void PrintUpdate(string trigger)
{
lock (printLock)
{
logger.Info(""); /***** DEADLOCKS HERE *****/
logger.Info($" {trigger}");
foreach (TrainingStatus status in trainingStatus.Values)
{
if (status.Status == TrainingStatus.UpdateStatus.Completed)
{
logger.Info(
$" {status.Status.ToString()} model {status.ThreadId + 1}",
100);
}
else
{
logger.Info(
$" {status.Status.ToString()} model {status.ThreadId + 1} working on epoch {status.Epoch} / {epochCount}",
100);
}
}
}
}
}
Определение работника
public class NetworkTrainer
{
IProgress<TrainingStatus> UpdateCompleted { get; set; }
private double TrainNetwork(ActivationNetwork network,
int epochCount,
int geneCount,
double[][] inputData,
double[][] outputData,
int threadId,
bool trimmedModel)
{
for (int idxEpoch = 0; idxEpoch < epochCount; ++idxEpoch)
{
error += teacher.RunEpoch(inputData,
outputData);
UpdateCompleted?.Report(new TrainingStatus
{
Epoch = idxEpoch,
Status = (trimmedModel) ? TrainingStatus.UpdateStatus.Trimmed : TrainingStatus.UpdateStatus.Untrimmed,
ThreadId = threadId,
});
}
return error;
}
}
Скриншот тупика