2016-11-24 3 views
1

Это то, что я пытаюсь достичь:таймаута Т трубопровод фильтр

Я использую TBB's конвейер для обработки. У меня есть несколько фильтров в конвейере, и мне нужно, чтобы фильтры были как можно быстрее, так как это приложение реального времени. Один из фильтров может занимать больше времени, чем я могу себе позволить, поэтому я хочу как-то установить тайм-аут на этом конкретном фильтре.

Посмотрев некоторое время я нашел следующее решение, которое работает в целом, но имеет свои проблемы:

Когда фильтр будет создан, создать мероприятие HANDLE

m_Event = CreateEvent(NULL, FALSE, FALSE, NULL); 

Затем фильтр вызывает функцию с помощью асинхр и ждет на мероприятии

... 
auto funcBind = std::bind(&MyFunc, ...) 
auto function = std::async(std::launch::async, funcBind, m_Event ...); 
long res = WaitForSingleObject(m_Event, delayMS); 
auto myFuncRes = function.get() 
if (res == WAIT_OBJECT_0 && (bool)myFuncRes) 
{ 
    // MyFunc Finished successfuly 
} 
else if (res == WAIT_TIMEOUT) 
{ 
    // Timeout expired 
} 
else 
{ 
    // MyFunc failed 
} 
... 
return; 

Как раз перед функцией MyFunc возвращается, она сигнализирует мероприятия

SetEvent(event); 

Так что теперь, если истекает delayMS таймаута, то Т фильтр не задерживает весь трубопровод. Проблема в том, что MyFunc все еще работает в фоновом режиме, это не останавливается.

Мой вопрос: есть ли лучший способ установить тайм-аут на TBB-фильтр, и есть ли решение остановить выполнение MyFunc после достижения таймаута (я бы предпочел не использовать таймеры или таймеры внутри него, возможно, каким-то образом использовать событие и проверить, было ли оно взято фильтром или что-то в этом роде)

ответ

3

Можно ли добавить контрольные точки в свою долговременную задачу? Если это возможно, вы можете использовать task_group или task_group_context, чтобы отменить выполнение задачи или несколько задач. Тем не менее, для правильной работы с долговременной задачей вам необходимо вручную ее прервать, проверив запрос на отмену через tbb::task::self().is_cancelled() и завершая выполнение задачи.

Затем вы можете использовать дополнительный поток для мониторинга времени и отправки запросов на отмену в группы задач, которые занимают больше времени, чем разрешено. Таким образом, ваши вычисления могут оставаться в том же потоке, что и конвейер, уменьшая накладные расходы от переключения и синхронизации между потоками.

Если ваш длинный поток связан с I/O, у вас есть другой вариант, введя асинхронный ввод-вывод, который лучше взаимодействует с TBB и дает вам весь контроль над временем.

+0

Спасибо. Отменяет ли task_group прекращение конвейера? Потому что я хочу только остановить длинный фильтр определенного шага. Я хочу, чтобы конвейер продолжался, как обычно, после этого –

+0

Нет, если вы запустили и отменили только фильтр в контексте task_group или другой области 'task_group_context :: isolated', а не контекст всего конвейера. Это означает, что внутри функтора фильтра вы хотите запустить другой вложенный алгоритм, например 'task_group :: run_and_wait()', чтобы он выполнялся в другом контексте – Anton

Смежные вопросы