2012-03-31 13 views
0

Dies ist eine vereinfachte Version eines Problems, mit dem ich mich beschäftige. Es hat eine Gewindeschleife, über die ich keine Kontrolle habe. Die Zeit für mich, eine Nachricht zu verarbeiten, ist mehr als die Zeit, die die Schleife werfen soll.Async von Async.AwaitEvent und Threading

Ich kann nichts in mytype neben dem markierten Abschnitt in StartAsync neu schreiben.

Können Sie mich zu den Anweisungen führen, die solche Bedingungen behandeln können? Gibt es zum Beispiel eine Version von syncContext.Post mit einer Warteschlange? Jede Hilfe willkommen

type mytype() = 
    let FinishedEvt = new Event<_>() 
    let FirstEvt  = new Event<_>() 
    member x.First  = FirstEvt.Publish 
    member x.Finished = FinishedEvt.Publish 

    member x.StartAsync() = 

    async { 
    let syncContext = match System.Threading.SynchronizationContext.Current with 
         | null -> new System.Threading.SynchronizationContext() 
         | other -> other 
    do! Async.SwitchToNewThread() 
    //**the code that I can change is here** 
    Thread.Sleep(100) 
    syncContext.Post(SendOrPostCallback(fun _ -> FirstEvt.Trigger ()), null) 
    Thread.Sleep(200) 
    syncContext.Post(SendOrPostCallback(fun _ -> FinishedEvt.Trigger()), null) 
    do! Async.SwitchToContext(syncContext) 
    () 
    } 
    let hopingobject = mytype() 
    let wf1 = lock readLock1 
        (fun() -> 
           async{ printfn "watching" 
             do! Async.AwaitEvent hopingobject.First 
             printfn "first event received" 
             do! Async.AwaitEvent hopingobject.Finished 
             printfn "I never get called"}) 

    hopingobject.StartAsync() |> Async.Start 
    wf1 |> Async.RunSynchronously 
    printfn "the end" 
    Console.ReadKey() |> ignore 

Antwort

2

Ich bin unklar, was Sie zu tun versuchen, und die Teile sind wesentlich, aber dieses Bit

async{ printfn "watching" 
     do! Async.AwaitEvent hopingobject.First 
     printfn "first event received" 
     do! Async.AwaitEvent hopingobject.Finished 
     printfn "I never get called"} 

scheint mir falsch, da Sie hören nicht starten für Beendet bis nach der Bearbeitung der Ersten, zu welchem ​​Zeitpunkt Fertigt bereits gefeuert haben kann. Vielleicht möchten Sie etwas mehr wie

async{ printfn "watching" 
     let! a = Async.AwaitEvent hopingobject.First |> Async.StartChild 
     let! b = Async.AwaitEvent hopingobject.Finished |> Async.StartChild 
     do! a 
     printfn "first event received" 
     do! b 
     printfn "hurray, I never called"} 

(Ich schreibe Code in einem Browser, hoffen, dass richtig ist.) Die Idee ist, am Anfang für beide hören beginnen, aber dann für die erste warten, und dann warten, Fertig.

+0

tatsächlich. Ich kann wahrscheinlich so mit dem Problem umgehen. Die Kombination von asynchronen Fortsetzungen mit der Thread-Funktion des Async-Moduls ist sehr wirkungsvoll. – nicolas

+0

mit diesem Konstrukt kann ich einige schwere Verarbeitung vor tun! b, und verpassen Sie nicht das beendete Ereignis, da seine Vollendung (alias der Ereigniszünden) in b erinnert wird. – nicolas

+0

eigentlich hatte ich inzwischen erkannt, dass ich viele angekettete Ereignisse beobachten müsste. Ich hätte AsyncObservable verwenden können, aber die Anzahl der Verkettungen ist nicht deterministisch. Also ging ich für einen Mailbox-Prozessor mit etwas Multithread-Synchronisation. Ich würde es nicht für eine Hochzeitsreise empfehlen. – nicolas