#multithreading #f# #cancellationtokensource #cancellation-token
#многопоточность #f# #cancellationtokensource #отмена-токен
Вопрос:
Я борюсь со следующим:
У меня есть система, которая имеет свой основной поток и имеет два фоновых потока, которые можно запускать и останавливать, но они обычно работают очень долго, поскольку останавливаются только во время изменений конфигурации.
Я обнаружил, что токен отмены в F # проверяется в асинхронных точках кода. Рабочие потоки не выполняют никаких асинхронных операций; они выполняют фоновую работу, но ничто не является асинхронным.
Упрощенная версия выглядит так:
let workerThread (someParameters) =
async {
while true do
setup some event driven system that has a callback when work is finished
on callback, signal
waitHandle.WaitOne()
}
и это начинается так:
Async.StartAsTask(workerThread parameter, cancellationToken = cancellationSource.Token)
Поскольку в системе нет абсолютно ничего асинхронного, токен отмены никогда не будет проверен, и, кроме того, мне нужно иметь возможность вручную проверять его в системах, управляемых событиями, которые продолжают настраиваться двумя рабочими потоками.
Как это можно сделать? В C # токен передается напрямую, и я могу проверить его, когда захочу.
Комментарии:
1. Разве вы не можете передать токен в качестве параметра
workerThread
?2. Да, я мог бы, но я предположил, возможно, ошибочно, что будет механизм для получения к нему доступа, поскольку он должен быть перенесен в поток
Ответ №1:
F # распространяет токен отмены на созданную задачу, но если рабочая функция заблокирована во время ожидания дескриптора, она не может проверить токен отмены. Чтобы решить эту проблему, вам также следует дождаться дескриптора ожидания токена отмены:
let workerThread () =
async {
let! token = Async.CancellationToken // this way you can get cancellation token
while true do
// whatever
WaitHandle.WaitAny([| waitHandle; token.WaitHandle |]) |> ignore
}