缺少IEvent,需要帮助才能完成此代码..我不明白如何制作触发器事件
// ----------------------------
// Listing 13-3.
open System
open System.Threading
open System.ComponentModel
open System.Windows.Forms
/// An IterativeBackgroudWorker follows the BackgroundWorker design pattern
/// but instead of running an arbitrary computation it iterates a function
/// a fixed number of times and reports intermediate and final results.
/// The worker is paramaterized by its internal state type.
///
/// Percentage progress is based on the iteration number. Cancellation checks
/// are made at each iteration. Implemented via an internal BackgroundWorker.
type IterativeBackgroundWorker<'a>(oneStep:('a -> 'a),
initialState:'a,
numIterations:int) =
let worker =
new BackgroundWorker(WorkerReportsProgress=true,
WorkerSupportsCancellation=true)
// The constructor captures the synchronization context. This allows us to post
// messages back to the GUI thread where the BackgroundWorker was created.
let syncContext = SynchronizationContext.Current
do if syncContext = null then failwith "no synchronization context found"
// Create the events that we will later trigger
let triggerStarted, started = IEvent.create()
let triggerCompleted,completed = IEvent.create()
let triggerError ,error = IEvent.create()
let triggerCancelled,cancelled = IEvent.create()
let triggerProgress ,progress = IEvent.create()
do worker.DoWork.Add(fun args ->
syncContext.Post(SendOrPostCallback(fun _ -> triggerStarted(DateTime.Now)),
state=null)
// This recursive function represents the computation loop.
// It runs at "maximum speed", i.e. is an active rather than
// a reactive process, and can only be controlled by a
// cancellation signal.
let rec iterate state i =
// At the end of the compuation terminate the recursive loop
if worker.CancellationPending then
args.Cancel <- true
elif i < numIterations then
// Compute the next result
let state' = oneStep state
// Report the percentage compuation and the internal state
let percent = int ((float (i+1)/float numIterations) * 100.0)
do worker.ReportProgress(percent, box state);
// Compute the next result
iterate state' (i+1)
else
args.Result <- box state
iterate initialState 0)
do worker.RunWorkerCompleted.Add(fun args ->
if args.Cancelled then triggerCancelled()
elif args.Error <> null then triggerError args.Error
else triggerCompleted (args.Result :?> 'a))
do worker.ProgressChanged.Add(fun args ->
triggerProgress (args.ProgressPercentage,(args.UserState :?> 'a)))
member x.WorkerCompleted = completed
member x.WorkerCancelled = cancelled
member x.WorkerError = error
member x.ProgressChanged = progress
// Delegate the remaining members to the underlying worker
member x.RunWorkerAsync() = worker.RunWorkerAsync()
member x.CancelAsync() = worker.CancelAsync()
/// The Started event gets raised when the worker starts. It is
/// raised on the GUI thread (i.e. in the synchronization context of
/// the thread where the worker object was created).
// It has type IEvent<DateTime>
member x.Started = started
let fibOneStep (fibPrevPrev:bigint,fibPrev) = (fibPrev, fibPrevPrev+fibPrev)
// ----------------------------
let worker = new IterativeBackgroundWorker<_>( fibOneStep,(1I,1I),100)
worker.WorkerCompleted.Add(fun result ->
MessageBox.Show(sprintf "Result = %A" result) |> ignore)
worker.ProgressChanged.Add(fun (percentage, state) ->
printfn "%d%% complete, state = %A" percentage state)
worker.RunWorkerAsync()
// ----------------------------
只需要知道如何制作一个稍后会触发的新事件。但如果有人想要帮助来完成代码,那么这将是一个很大的谢谢:D
答案 0 :(得分:1)
来自文档:
open System.Collections.Generic
type MyClassWithCLIEvent() =
let event1 = new Event<_>()
[<CLIEvent>]
member this.Event1 = event1.Publish
member this.TestEvent(arg) =
event1.Trigger(this, arg)
let classWithEvent = new MyClassWithCLIEvent()
classWithEvent.Event1.Add(fun (sender, arg) ->
printfn "Event1 occurred! Object data: %s" arg)
classWithEvent.TestEvent("Hello World!")
答案 1 :(得分:1)
Daniel发布的代码应该给你答案。只需将其链接到Expert F#书的(第一版)中的代码,更改为:
IEvent.create()
函数已被类型替换,因此您将使用new Event<_>()
Trigger
成员IEvent
值)是对象的Publish
成员CLIEvent
属性,则事件将编译为.NET事件(否则它将只是IEvent
类型的属性)我相信这些是用于处理事件的API中唯一的重大变化。还有一个新模块Observable
包含与Event
相同的功能(例如Event.map
),通常最好使用可观察的实现(它更标准,避免潜在的内存泄漏) )。