我寫了一系列的F#圖的搜索算法,並認爲這將是很好的採取並行的優勢。我想要並行執行多個線程,並將第一個線程的結果完成。我有一個實現,但它不漂亮。加入第一道成品線?
兩個問題:是有這種功能的標準名稱?不是Join或JoinAll,而是JoinFirst?其次,是否有更習慣的方式來做到這一點?
//implementation
let makeAsync (locker:obj) (shared:'a option ref) (f:unit->'a) =
async {
let result = f()
Monitor.Enter locker
shared := Some result
Monitor.Pulse locker
Monitor.Exit locker
}
let firstFinished test work =
let result = ref Option.None
let locker = new obj()
let cancel = new CancellationTokenSource()
work |> List.map (makeAsync locker result) |> List.map (fun a-> Async.StartAsTask(a, TaskCreationOptions.None, cancel.Token)) |> ignore
Monitor.Enter locker
while (result.Value.IsNone || (not <| test result.Value.Value)) do
Monitor.Wait locker |> ignore
Monitor.Exit locker
cancel.Cancel()
match result.Value with
| Some x-> x
| None -> failwith "Don't pass in an empty list"
//end implentation
//testing
let delayReturn (ms:int) value =
fun()->
Thread.Sleep ms
value
let test() =
let work = [ delayReturn 1000 "First!"; delayReturn 5000 "Second!" ]
let result = firstFinished (fun _->true) work
printfn "%s" result
如果必須將結果存儲在共享的狀態,爲什麼不能讓每個工作者線程定期檢查,如果已經產生的結果,如果是這樣,結束?然後你可以使用['Async.Parallel'](http://msdn.microsoft.com/en-us/library/ee353779.aspx),你的代碼應該相對簡單。 – Daniel
兩個原因,建築和實用。在架構上,我的搜索算法不需要知道並行化的細節,也不需要知道它們是否並行運行。實際上,圖搜索是大量遞歸的;共享狀態是針對單個節點的孩子的。在所有節點之間共享該狀態將會很糟糕。 – zmj
我建議選擇'async'或'Task',並堅持下去,但不要混合兩者。他們是做同樣事情的兩種方式。在F#中'async'更具慣用性。 – Daniel