Извините за заголовок, я не мог найти лучшего объяснения моей проблемы...
Мне трудно синхронизировать разные потоки в моем приложении. Вероятно, это простая проблема для тех, кто по-новому смотрит на проблему, но после нескольких часов исследований тупиковой ситуации моя голова взрывается, и я не могу найти хороший и безопасный способ написать свой механизм синхронизации :(
По сути, у меня есть процесс .Net, который работает в нескольких потоках (все в одном процессе, поэтому нет необходимости в IPC). У меня есть 4 темы:
- 1 поток, скажем, он называется SpecificThread. Есть
System.Timers.Timer
, который периодически выполняет какой-то код. - 3 других потока, каждый из которых запускает службу, которая периодически выполняет некоторый код (цикл
while (true)
+Thread.Sleep(few ms)
).
Все 3 службы должны работать одновременно. Я гарантирую, что их параллельное выполнение является потокобезопасным. Четвертый поток, SpecificThread, должен периодически выполнять свой код, но он должен блокировать выполнение трех других служб.
Итак, у меня есть SpecificThread, который периодически выполняет код. Когда SpecificThread хочет периодически выполнять свой код, он должен ждать, пока другие службы завершат свою задачу. Когда все остальные 3 службы завершили свою задачу, она должна выполнить свой SpecificCode, в то время как другие 3 службы заблокированы. Когда его SpecificCode выполняется, другие 3 службы могут снова запустить свой код.
У меня есть общий экземпляр объекта SynchronizationContext
, который используется всеми 4 потоками. Я могу использовать его для синхронизации своих потоков:
public class SynchronizationContext
{
public void StartService1()
{
...
}
public void StopService1()
{
...
}
...
public void StartSpecificCode()
{
// Some sync here that wait until all 3 services completed their
// respective tasks
}
public void NotifySpecificCodeCompleted()
{
// Some sync here that allows services 1 to 3 to execute again
}
}
Механизм выполнения 3 сервисов выглядит так:
// Only exits the loop when stopping the whole .Net process
while (myService.IsRunning)
{
try
{
this.synchronizationContext.StartService1();
// Do some job
}
finally
{
this.synchronizationContext.EndService1();
// Avoids too much CPU usage for nothing in the loop
Thread.Sleep(50);
}
}
Механизм выполнения SpecificThread:
// System.Timers.Timer that is instantiated on process start
if (this.timer != null)
{
this.timer.Stop();
}
try
{
// Must blocks until computation is possible
this.synchronizationContext.StartSpecificCode();
// Some job here that must execute while other 3
// services are waiting
}
finally
{
// Notify computation is done
this.synchronizationContext.NotifySpecificCodeCompleted();
// Starts timer again
if (this.timer != null)
{
this.timer.Start();
}
}
Я не могу понять, как использовать критические разделы, так как только SpecificThread
должен работать, пока другие ждут. Я не нашел способа ни с Semaphore
, ни с AutoResetEvent
(их использование привело к трудной для отладки взаимоблокировке в моем коде). У меня заканчиваются идеи... Может быть, Interlocked
статические методы помогут?
Последнее слово: мой код должен работать с .Net 3.5, я не могу использовать ни TPL, ни классы CountdownEvent
...
Любая помощь приветствуется!