Предположим, что есть много потоков, вызывающих Do()
, и только один рабочий поток обрабатывает фактическую работу.
void Do(Job job)
{
concurrentQueue.Enqueue(job);
// wait for job done
}
void workerThread()
{
while (true)
{
Job job;
if (concurrentQueue.TryDequeue(out job))
{
// do job
}
}
}
Do() должен дождаться завершения работы перед возвратом. Поэтому я написал следующий код:
class Task
{
public Job job;
public AutoResetEvent ev;
}
void Do(Job job)
{
using (var ev = new AutoResetEvent(false))
{
concurrentQueue.Enqueue(new Task { job = job, ev = ev }));
ev.WaitOne();
}
}
void workerThread()
{
while (true)
{
Task task;
if (concurrentQueue.TryDequeue(out task))
{
// do job
task.ev.Set();
}
}
}
После некоторых тестов я обнаружил, что он работает так, как ожидалось. Однако я не уверен, что это хороший способ выделить много AutoResetEvents или есть лучший способ сделать это?
TaskCompletionSource
для отображения объектов TPLTask
вместо ваших пользовательскихTask
, что даст возможность дождаться завершения задания в качестве дополнительного преимущества. - person Dmytro Mukalov   schedule 23.04.2019Do
должен ждать завершения задания, то зачем запускать его в отдельном рабочем потоке? - person Sean   schedule 23.04.2019WaitOne
только один раз перед удалением примитива, не имеет значения, используете ли выAutoResetEvent
илиManualResetEvent
. Так почему бы не использовать более легкий вариантManualResetEventSlim
. и эффективный? - person Theodor Zoulias   schedule 23.04.2019ManualResetEventSlim
не будет иметь большого значения, поскольку ожидается, что время ожидания будет долгим. Кажется, что ваш дизайн в любом случае не сосредоточен на производительности. У вас может быть какая-то конкретная причина (сходство с потоком?), чтобы заставить все задания выполняться определенным потоком. - person Theodor Zoulias   schedule 23.04.2019TaskCompletionSource
. - person Theodor Zoulias   schedule 23.04.2019