Мало проблем с вашим кодом:
1) Если вы используете задания Quartz без сохранения состояния, ваша блокировка не принесет пользы.Кварц создает новый экземпляр задания каждый раз, когда запускает триггер.Вот почему вы видите, что один и тот же аккаунт обрабатывается дважды.Это будет работать, только если вы используете работу с состоянием (IStatefulJob).Или сделайте блокировку статической, но продолжайте читать.
2) Даже если 1) зафиксирован, это лишит цели наличия нескольких потоков, поскольку все они будут ожидать друг друга в одной и той же блокировке.С таким же успехом у вас может быть одна нить.
Я недостаточно знаю о требованиях, особенно о том, что происходит в // stuff
.Возможно, вам не нужен этот код для запуска в нескольких потоках, и последовательное выполнение будет работать нормально.Я предполагаю, что это не так, и вы хотите запустить его в несколько потоков.Самый простой способ - иметь только одну работу в Кварце.В этом задании загрузите учетные записи в чанках, скажем, 100 заданий в каждом чанке.Это даст вам 5 кусков, если у вас есть 500 учетных записей.Перенести каждую обработку чанка в пул потоков .Он позаботится об использовании оптимального количества потоков.Это была бы Очередь Производителя Потребителя бедного человека.
public void Execute(JobExecutionContext context) {
var linqFindAccount = from Account in MainAccounts
where Account.Done == false
select Account;
IList<IList<Account>> chunks = linqFindAccount.SplitIntoChunks(/* TODO */);
foreach (IList<Account> chunk in chunks) {
ThreadPool.QueueUserWorkItem(DoStuff, chunk);
}
}
private static void DoStuff(Object parameter) {
IList<Account> chunk = (IList<Account>) parameter;
foreach (Account account in chunk) {
// stuff
}
}
Как обычно, с несколькими потоками вы должны быть очень осторожны с доступом к изменяемому общему состоянию.Вы должны убедиться, что все, что вы делаете в методе DoStuff, не вызовет нежелательных побочных эффектов.Вы можете найти это и это полезным.