У меня есть проблема относительно многопоточности и вставки объекта к Словарю. Следующая ситуация - то, что я - encoutering, когда insertingen подвергает с дублирующимся идентификатором:
private static readonly Timer bufferChecker;
private static readonly List<SubjectStartRulePair> inBuffer;
private static readonly IDictionary<Guid, Subject> beingProcessed;
private static readonly object objLock;
static InBuffer()
{
objLock = new object();
inBuffer = new List<SubjectStartRulePair>();
beingProcessed = new Dictionary<Guid, Subject>();
bufferChecker = new Timer(x => ProcessThreads(), null, 1000, 1000);
}
public static void ProcessThreads()
{
lock(objLock)
{
var bufferedItems = inBuffer.OrderBy(x => x.QueuedTime);
foreach (var item in bufferedItems)
{
if (!beingProcessed.ContainsKey(item.Subject.SubjectId)) //Important check which validates if there is already a Thread running
{
var thread = new Thread(
x =>
{
//Thread #2 is here and runs into duplicate Key
beingProcessed.Add(item.Subject.SubjectId, item.Subject);
item.StartRule(item.Subject);
beingProcessed.Remove(item.Subject.SubjectId);
});
thread.Start();
inBuffer.Remove(item);
}
}
}
}
public static void TryToExecute(Subject subject, IBusinessRule rule)
{
lock (objLock)
{
if (beingProcessed.ContainsKey(subject.SubjectId)) //Important check which validates if there is already a Thread running
{
inBuffer.Add(
new SubjectStartRulePair
{
QueuedTime = DateTime.Now,
Subject = subject,
StartRule = (x =>
{
rule.RunChildren(subject);
return true;
})
}
);
}
else
{
var thread = new Thread(
x =>
{
beingProcessed.Add(subject.SubjectId, subject);
rule.RunChildren(subject);
beingProcessed.Remove(subject.SubjectId);
});
thread.Start(); //Thread #1 is here
}
}
}
Я заблокировал оба метода, но блокировка, кажется, не работает... Кажется, что два потока оба вводят блокировку в различные методы. Я упускаю суть использования блокировки ()? Какая-либо идея о том, как я должен реализовать это правильно? Важная заметка на полях, ProcessThreads () метод называет каждую секунду Таймер (bufferChecker).
Вы запускаете новый поток в каждом методе - эти новые потоки не будут иметь (или запрашивать) блокировку.
Таким образом, хотя только один из ProcessThreads
или TryToExecute
может эффективно выполняться одновременно, вы не можете контролировать биты в лямбда-выражениях. Если они также требуют взаимного исключения, вам нужно поместить в эти лямбды оператор lock
.