Я пробовал следующее:
let o = Object()
let print message =
// lock to make the console output cleaner
lock o (fun _ -> printfn $"{message}")
let doAndWait name =
print $"start {name}"
Thread.Sleep(TimeSpan.FromSeconds(1))
print $"end {name}"
1
let a = backgroundTask { return doAndWait "A" }
let b = backgroundTask { return doAndWait "B" }
print "waiting for nothing"
Thread.Sleep(TimeSpan.FromSeconds(3))
print $"finished: {r.Result}"
let c = a.Result + b.Result
printfn $"finished: {c}"
Мое, очевидно ошибочное, ожидание состояло в том, что фоновые задачи будут запускаться в пуле потоков, и я смогу собрать результаты позже.
На практике выполняется «a», затем выполняется «b», затем выполняется код «ничего не ждать». Таким образом, выполнение является чисто последовательным.
Я ожидал такого поведения:
let x = async { return doAndWait "X" }
let y = async { return doAndWait "Y" }
let r =
async {
let! x' = x
let! y' = y
return x' + y'
}
|> Async.StartAsTask
print "waiting for nothing"
Thread.Sleep(TimeSpan.FromSeconds(3))
print $"finished: {r.Result}"
Итак, я не понимаю, что такое CE backgroundTask. Поиск в Google бесполезен, учитывая количество проиндексированных строк «backgroundTask»: D
@ДжимФой, что ты имеешь в виду? это просто тест для понимания backgroundTask CE
Консоль или графический интерфейс?
это простой консольный тест, вы можете скопировать/вставить его как есть, и он запустится (возможно, вам нужно добавить к нему операторы open)
backgroundTask
завершается синхронно при запуске в потоке пула потоков
Я смотрю на документы здесь:
https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/task-expressions#background-tasks
Это говорит
A background task ignores any SynchronizationContext.Current in the following sense: if started on a thread with non-null SynchronizationContext.Current, it switches to a background thread in the thread pool using Task.Run. If started on a thread with null SynchronizationContext.Current, it executes on that same thread.
В приложении с графическим интерфейсом SynchronizationContext.Current будет ненулевым, поэтому в этом случае backgroundTask переключится на пул потоков. Поскольку вы находитесь в консольном приложении, SynchronizationContext.Current будет иметь значение null, поэтому backgroundTask выполняется в том же потоке.
Я на самом деле не пробовал, но я думаю, что это то, что происходит.
Я думаю, вы можете быть правы. Есть ли способ изменить контекст синхронизации для основного потока? Я смотрю на запуск фоновых задач в другом потоке и собираю результаты позже
Да, но в вашем случае вы можете просто использовать задачу вместо фоновой задачи, а затем собирать результаты с помощью Task.WaitAll(). Вам действительно не нужно беспокоиться о контексте синхронизации.
Что это за программа?