TP

F# Parallel Extras (III.): Financial dashboard with cancellation

In this article we'll look at several improvements that can be done to the Financial dashboard example (originally from the Parallel Programming with Microsoft .NET book). When I was translating samples in the book from C# to F#, the sample struck me, because it looks like a perfect fit for F# asynchronous workflows (instead of the Task<T> type used in the C# version). I already talked about an alternative implementation based on asynchronous workflows. However that version was still following some of the programming patterns, from the original C# version, which are not idiomatic in F#. In this article, I'll talk about a few other improvements that we can make to the sample...

In the original version of the sample (in both C# and F#), we explicitly checked whether a cancellation token has been cancelled in every single operation. This was needed in C#, because tasks do not support cancellation automatically. However, F# asynchronous workflows make cancellation easier. They automatically check if the computation should be cancelled at the beginning and the end of every asynchronous call. Our first change will be to use this feature. Also, the original version propagates a null value when the computation is cancelling. In F# we don't need that and we'll only change the type of the overall result to option<T>, so that we can notify the user interface (but we don't need to propagate cancellation explicitly). Finally, the original version contained sequential implementation, but didn't provide any way of actually running it, so we'll do a bit of refactoring to make that sample actually useable.

Representing analysis process

Let's start with the refactoring. The original C# version (as well as the task-based F# implementation) returns a record with Task<T> values, which allows the user interface to wait for the result using ContinueWith method (the code is available on CodePlex, if you want to take a look). In the previous article, we used events instead, but only in the version based on asynchronous workflows. A more convenient option is to encapsulate the reporting of status (implemented using events) in an abstract class that will represent the computation (or analysis process). The class can then be created and returned by various implementations of the financial calculation. Even though abstract classes are very object oriented, it will work very well in this case, because it can hide some implementation and we'll be able to create it using object expressions.

The following snippet implements the class (the listing hides some of the event declarations, because they all follow the same pattern). The class simply exposes several events and allows the user of the class to trigger them. More interestingly, the class also provides method for starting and cancelling the computation. It is worth noting that the original version of the sample returned a computation that was already running. This is not perfect (at least when using events), because a user may want to setup handlers for the events first and start the computation after that, to make sure that no event occurrences are missed.

 1: [<AbstractClass>]
 2: type AnalysisProcess() = 
 3: 
 4:     // Trigger event on the GUI thread using a captured dispatcher
 5:     let guiDispatch = Windows.Threading.Dispatcher.CurrentDispatcher
 6:     let triggerGuiEvent (e:Event<_>) v = 
 7:         guiDispatch.Invoke(new Action(fun () -> 
 8:               e.Trigger(v) ), [| |]) |> ignore
 9: 
10:     // Create events that are used to notify the 
11:     // caller about partial results of the computation
12:     let loadNyseDataEvt = new Event<StockDataCollection>()
13:     let compareModelsEvt = new Event<MarketRecommendation option>()
14:     let errorHandlerEvt = new Event<unit>()
15:     (other events omitted)
16: 
17:     /// Start the analysis (to be used after handlers are registered)
18:     abstract Start : unit -> unit
19:     /// Try to cancel the process (if it has been already started)
20:     abstract TryCancel : unit -> unit
21: 
22:     // Expose events to the user interface layer
23:     member x.LoadNyseData = loadNyseDataEvt.Publish
24:     member x.CompareModels = compareModelsEvt.Publish
25:     member x.ErrorHandler = errorHandlerEvt.Publish 
26:     // Trigger event (called from the computation engine)
27:     member x.TriggerLoadNyseData(v) = triggerGuiEvent loadNyseDataEvt v
28:     member x.TriggerCompareModels(v) = triggerGuiEvent compareModelsEvt v
29:     member x.TriggerErrorHandler(v) = triggerGuiEvent errorHandlerEvt v
30:     (other members omitted)F# Web Snippets

The type declaration is marked with the AbstractClass attribute, which instructs the F# compiler to treat it as an abstract class. The abstract members of the class are Start and TryCancel. Both of the members are quite simple and don't take any arguments or return any result. They simply start the computation or trigger its cancellation.

Aside from abstract members, the type creates and exposes several event values. In the constructor, we capture the current WPF Dispatcher (assuming that the type is first constructed on the main GUI thread) and when triggering an event, we dispatch the call to the original thread. This is done using a simple helper function triggeGuiEvent that was already discussed in the previous article. For every event, we have a private event value (e.g. loadNyseDataEvt) and two public members (e.g. LoadNyseData and TriggerLoadNyseData). The first member exposes the event and is used from the user interface when registering event handlers. The other member is used from the computation engine to report results to the GUI. Note that the CompareModels event carries MarketRecommendation option as a value. This event will be triggered even if a computation is cancelled, in which case the value will be None (other events may not fire when we cancel the computation).

Creating sequential implementation

To demonstrate how a computation would construct and return an implementation of the above abstract class, let's start by looking at the sequential implementation. In the sequential version, we'll ignore cancellation (adding it would be simple - we'd just set a flag and check whether it was set after every step). Even though this is fully sequential, we'll do the actual work in background (to avoid blocking the GUI thread):

 1: // Implements market analysis using sequential computation
 2: let sequentialAnalysis() = 
 3: 
 4:   // Analysis engine that will be returned as the result.
 5:   let rec engine = 
 6:     { new AnalysisProcess() with
 7:         member x.Start() = Task.Factory.StartNew(analysis) |> ignore
 8:         member x.TryCancel() = () }
 9: 
10:   // Function that implements the sequential analysis
11:   and analysis() =
12:       (loading and processing omitted)
13:   
14:       // Run both models and compare them
15:       let modeledMarketData = runModel analyzedStockData
16:       engine.TriggerModelMarketData(modeledMarketData)
17:       let modeledHistoricalData = runModel analyzedHistoricalData
18:       engine.TriggerModelHistoricalData(modeledHistoricalData)
19:       let recommendation = compareModels [ modeledMarketData; modeledHistoricalData ]
20:       engine.TriggerCompareModels(Some recommendation)
21:   engineF# Web Snippets

The snippet creates a recursive reference between the analysis function and the engine value. In this case, F# compiler inserts some runtime checks to verify that the recursion makes sense and it shows a warning that notifies us about this (we can safely ignore it by adding #nowarn "40"). The engine value is created using object expression and it adds implementation of the two abstract members of the AnalysisProcess class. In the Start member, it creates a task that will start running the analysis function. In the other way round, the analysis function calls members of the engine value to report intermediate progress of the computation (for example by calling the TriggercompareModels member at the end).

Supporting cancellation in asynchronous workflows

The asynchronous implementation of the computation will follow the same pattern. We'll create an engine value that implements the abstract class and we'll have a computation (asynchronous workflow instead of an ordinary function) that will be started from the Start method and will report the progress by calling engine.TriggerXyz members. The following snippet shows the overall structure (implementation of the computation is hidden, as we'll discuss it in the next section):

 1: // Implements market analysis using F# asynchronous workflows
 2: let asyncAnalysis() = 
 3:   let cts = new CancellationTokenSource()
 4: 
 5:   // Analysis engine that will be returned as the result.
 6:   let rec engine = 
 7:     { new AnalysisProcess() with
 8:         member x.Start() = 
 9:           // Start workflow with cancellation token
10:           Async.Start(compare, cancellationToken = cts.Token)
11:         member x.TryCancel() = cts.Cancel() }
12: 
13:   // Load & process NYSE and NASDAQ data
14:   and marketModel = (...)
15:   // Load & process FED data
16:   and historicalModel = (...)
17: 
18:   // Run both of the models and compare them to get recommendation
19:   and compare = (...)
20: 
21:   // Return the created engine
22:   engineF# Web Snippets

The computation is constructed in almost the same way as in the the previous article. We first create two workflows (marketModel and historicalModel) that construct two models and are called from compare computation in parallel. However, there is one important difference to enable automatic cancellation, but we'll discuss that in the next section.

To support cancellation, the function first creates an instance of CancellationTokenSource. When starting the workflow, we pass a token from the cancellation source to the Async.Start operation. When the user requests cancellation we call the Cancel method of the token source. As already discussed, we don't need to explicitly check whether the token was set anywhere in the workflow, because this is done automatically. However, we need to write the asynchronous computation in a way that makes this possible.

Creating computations with cancellation support

If we pass a cancellation token when starting asynchronous workflow, it will automatically check whether the cancellation was requested around every yield point. A yield point is when the control is transferred from the user code to the workflow to perform an asynchronous operation, which is done either using let!, do! or return! Asynchronous workflow does not attempt to cancel the computation actively (e.g. by calling Thread.Abort), because this is considered as dangerous. Instead it uses cooperative cancellation, which is deterministic. In practice, this means that if you have a workflow that should be cancelled, it should make all calls to non-trivial operations asynchronously (and so all the operations need to be written as asynchronous too). The following example demonstrates this practice (some parts are hidden, to make the code shorter, but you can see the idea):

 1: // Load & process NYSE and NASDAQ data
 2: and marketModel = async {
 3:     // Start loading data asynchronously in background
 4:     let! nyse = 
 5:       asyncLoadNyseData() 
 6:         |> Async.WithResult engine.TriggerLoadNyseData 
 7:         |> Async.StartChild
 8:     let! nasdaq = 
 9:         asyncLoadNasdaqData() 
10:         |> Async.WithResult engine.TriggerLoadNasdaqData 
11:         |> Async.StartChild
12: 
13:     (waiting for completion and normalization omitted)
14:     let! analyzed = asyncAnalyzeData normalized 
15:     engine.TriggerAnalyzeMarketData(analyzed)
16:     let! res = asyncRunModel analyzed 
17:     engine.TriggerModelMarketData(res)
18:     return res }
19: 
20: // Load & process FED data
21: and historicalModel = async {
22:     (loading and normalization omitted)
23:     let! analyzed = asyncAnalyzeData normalized
24:     engine.TriggerAnalyzeHistoricalData(analyzed)
25:     let! res = asyncRunModel analyzed 
26:     engine.TriggerModelHistoricalData(res)
27:     return res }F# Web Snippets

In order to write the code in this way, I needed to add a couple of functions to the main module that implements the financial analysis. As you can see, when performing some operation we call functions like asyncAnalyzeData or asyncRunModel instead of the usual analyzeData and runModel from the sequential version. These asynchronous versions simply wrap a call to the synchronous version, which means that the workflow can be cancelled only after the underlying operation completes. If we wanted to support cancellation in a more granular way, we'd need to modify these functions and insert additional yield points inside them.

When doing a call inside asynchronous workflow (e.g. using let! or Async.StartChild), the cancellation token is automatically propagated. However, if you needed to call a long-running operation that isn't itself implemented using asynchronous workflows (and you cannot change it), you can use the Async.CancellationToken primitive to get the current token. The following snippet shows a very basic example:

1: let work = async { 
2:   let! tok = Async.CancellationToken
3:   let res = longRunningOp tok 
4:   return! asynchronousOp res }F# Web Snippets

The computation starts by getting a cancellation token (which is an asynchronous operation, because it is available only in the asynchronous context) and then calls the longRunningOp with the token as an argument. The operation returns some value (and may return early if the cancellation was triggered). When the cancellation is triggered, the asynchronous workflow will be cancelled at the next yield point (in this case the return! call) and so the rest of the workflow will not be executed. Note that we're not notified about the cancellation inside the workflow in any way (because it just stops running). The reaction to the cancellation has to be provided more explicitly...

Handling cancellation

Let's get back to our example with financial modeling. When the workflow is cancelled, we want to call the TriggerCompareModels method with a None value as the argument, so that the user interface can react. We'll add cancellation handling to the main workflow compare, which also uses try...with construct to handle exceptions that may occur during the modeling. Unlike exception handling, there is no built-in construct to handle cancellation, so we'll need to write the handling using a method call. This can be done using Async.TryCancelled:

 1: // When the workflow is cancelled, return 'None' as the result
 2: and compare = 
 3:   Async.TryCancelled
 4:     (async {
 5:       try
 6:           let! models = Async.Parallel [ marketModel; historicalModel ]
 7:           let res = compareModels models 
 8:           engine.TriggerCompareModels(Some res)
 9:       with e ->
10:           engine.TriggerErrorHandler()  },
11:       fun ce -> 
12:           engine.TriggerCompareModels(None))F# Web Snippets

The TryCancelled operation takes an asynchronous workflow as the first argument and a compensation function as the second. It returns a new workflow that runs the wrapped workflow and when a cancellation occurs in the wrapped workflow, it calls the provided compensation function. In the example above, we combine the call with the try...with construct to handle all possible "wrong situations".

The overall behavior of the computation if nothing wrong happens is that it runs and compares the two financial models and report the result to the GUI. When some part of the computation fails (and throws an exception), the workflow calls the TriggerErrorHandler (to notify GUI about an error) and when the operation is cancelled (by the user) the workflow calls TriggerCompareModels with empty result as the argument.

Summary

In this article, we looked at an improved F# version of the Financial dashboard example from the Parallel Programming with Microsoft .NET book. We started with a version discussed in my earlier article , did a minor refactoring to make reporting progress to the user interface easier and used this change to write a sequential version of the code that can be actually started. More interestingly, we also discussed the problem of cancellation in F# asynchronous workflows. Unlike .NET 4.0 tasks, asynchronous workflows support automatic (cooperative) cancellation. The basic steps to support cancellation that we demonstrated are:

Source Code

val work : Async<int>

Full name: Untitled.work
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val tok : CancellationToken

  type: CancellationToken
  inherits: ValueType
Multiple items
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>

--------------------

type Async
with
  static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
  static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
  static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
  static member AwaitTask : task:Tasks.Task<'T> -> Async<'T>
  static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
  static member CancelDefaultToken : unit -> unit
  static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
  static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
  static member Ignore : computation:Async<'T> -> Async<unit>
  static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
  static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
  static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
  static member Sleep : millisecondsDueTime:int -> Async<unit>
  static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
  static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:Tasks.TaskCreationOptions * ?cancellationToken:CancellationToken -> Tasks.Task<'T>
  static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
  static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:Tasks.TaskCreationOptions -> Async<Tasks.Task<'T>>
  static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
  static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
  static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
  static member SwitchToNewThread : unit -> Async<unit>
  static member SwitchToThreadPool : unit -> Async<unit>
  static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
  static member CancellationToken : Async<CancellationToken>
  static member DefaultCancellationToken : CancellationToken
end

Full name: Microsoft.FSharp.Control.Async
property Async.CancellationToken: Async<CancellationToken>
val res : int

  type: int
  implements: IComparable
  implements: IFormattable
  implements: IConvertible
  implements: IComparable<int>
  implements: IEquatable<int>
  inherits: ValueType
val longRunningOp : CancellationToken -> int

Full name: Untitled.longRunningOp
val asynchronousOp : int -> Async<int>

Full name: Untitled.asynchronousOp
type AbstractClassAttribute =
  class
    inherit Attribute
    new : unit -> AbstractClassAttribute
  end

Full name: Microsoft.FSharp.Core.AbstractClassAttribute

  type: AbstractClassAttribute
  implements: Runtime.InteropServices._Attribute
  inherits: Attribute
type AnalysisProcess =
  class
    new : unit -> AnalysisProcess
    abstract member Start : unit -> unit
    abstract member TryCancel : unit -> unit
    member TriggerAnalyzeHistoricalData : v:StockAnalysisCollection -> unit
    member TriggerAnalyzeMarketData : v:StockAnalysisCollection -> unit
    member TriggerCompareModels : v:MarketRecommendation option -> unit
    member TriggerErrorHandler : v:unit -> unit
    member TriggerLoadFedHistoricalData : v:StockDataCollection -> unit
    member TriggerLoadNasdaqData : v:StockDataCollection -> unit
    member TriggerLoadNyseData : v:StockDataCollection -> unit
    member TriggerMergeMarketData : v:StockDataCollection -> unit
    member TriggerModelHistoricalData : v:MarketModel -> unit
    member TriggerModelMarketData : v:MarketModel -> unit
    member TriggerNormalizeHistoricalData : v:StockDataCollection -> unit
    member TriggerNormalizeMarketData : v:StockDataCollection -> unit
    member AnalyzeHistoricalData : IEvent<StockAnalysisCollection>
    member AnalyzeMarketData : IEvent<StockAnalysisCollection>
    member CompareModels : IEvent<MarketRecommendation option>
    member ErrorHandler : IEvent<unit>
    member LoadFedHistoricalData : IEvent<StockDataCollection>
    member LoadNasdaqData : IEvent<StockDataCollection>
    member LoadNyseData : IEvent<StockDataCollection>
    member MergeMarketData : IEvent<StockDataCollection>
    member ModelHistoricalData : IEvent<MarketModel>
    member ModelMarketData : IEvent<MarketModel>
    member NormalizeHistoricalData : IEvent<StockDataCollection>
    member NormalizeMarketData : IEvent<StockDataCollection>
  end

Full name: Untitled.AnalysisProcess

Abstract class that allows the ViewModel component to react to completion
 of a task or asynchronous workflow running in background.
 This type is returned from AnalysisEnginge from 'DoAnalysis' method

val guiDispatch : Windows.Threading.Dispatcher
namespace System.Windows
namespace System.Windows.Threading
type Dispatcher =
  class
    member BeginInvoke : System.Windows.Threading.DispatcherPriority * System.Delegate -> System.Windows.Threading.DispatcherOperation
    member BeginInvoke : System.Delegate * obj [] -> System.Windows.Threading.DispatcherOperation
    member BeginInvoke : System.Windows.Threading.DispatcherPriority * System.Delegate * obj -> System.Windows.Threading.DispatcherOperation
    member BeginInvoke : System.Delegate * System.Windows.Threading.DispatcherPriority * obj [] -> System.Windows.Threading.DispatcherOperation
    member BeginInvoke : System.Windows.Threading.DispatcherPriority * System.Delegate * obj * obj [] -> System.Windows.Threading.DispatcherOperation
    member BeginInvokeShutdown : System.Windows.Threading.DispatcherPriority -> unit
    member CheckAccess : unit -> bool
    member DisableProcessing : unit -> System.Windows.Threading.DispatcherProcessingDisabled
    member HasShutdownFinished : bool
    member HasShutdownStarted : bool
    member Hooks : System.Windows.Threading.DispatcherHooks
    member Invoke : System.Windows.Threading.DispatcherPriority * System.Delegate -> obj
    member Invoke : System.Delegate * obj [] -> obj
    member Invoke : System.Windows.Threading.DispatcherPriority * System.Delegate * obj -> obj
    member Invoke : System.Windows.Threading.DispatcherPriority * System.TimeSpan * System.Delegate -> obj
    member Invoke : System.Delegate * System.Windows.Threading.DispatcherPriority * obj [] -> obj
    member Invoke : System.Delegate * System.TimeSpan * obj [] -> obj
    member Invoke : System.Windows.Threading.DispatcherPriority * System.Delegate * obj * obj [] -> obj
    member Invoke : System.Windows.Threading.DispatcherPriority * System.TimeSpan * System.Delegate * obj -> obj
    member Invoke : System.Delegate * System.TimeSpan * System.Windows.Threading.DispatcherPriority * obj [] -> obj
    member Invoke : System.Windows.Threading.DispatcherPriority * System.TimeSpan * System.Delegate * obj * obj [] -> obj
    member InvokeShutdown : unit -> unit
    member Thread : System.Threading.Thread
    member VerifyAccess : unit -> unit
    static member CurrentDispatcher : System.Windows.Threading.Dispatcher
    static member ExitAllFrames : unit -> unit
    static member FromThread : System.Threading.Thread -> System.Windows.Threading.Dispatcher
    static member PushFrame : System.Windows.Threading.DispatcherFrame -> unit
    static member Run : unit -> unit
    static member ValidatePriority : System.Windows.Threading.DispatcherPriority * string -> unit
  end

Full name: System.Windows.Threading.Dispatcher
property Windows.Threading.Dispatcher.CurrentDispatcher: Windows.Threading.Dispatcher
val triggerGuiEvent : (Event<'a> -> 'a -> unit)
val e : Event<'a>
Multiple items
module Event

from Microsoft.FSharp.Control

--------------------

type Event<'Delegate,'Args (requires delegate and 'Delegate :> Delegate)> =
  class
    new : unit -> Event<'Delegate,'Args>
    member Trigger : sender:obj * args:'Args -> unit
    member Publish : IEvent<'Delegate,'Args>
  end

Full name: Microsoft.FSharp.Control.Event<_,_>

--------------------

type Event<'T> =
  class
    new : unit -> Event<'T>
    member Trigger : arg:'T -> unit
    member Publish : IEvent<'T>
  end

Full name: Microsoft.FSharp.Control.Event<_>
val v : 'a
Multiple overloads
Windows.Threading.Dispatcher.Invoke(method: Delegate, args: obj []) : obj
Windows.Threading.Dispatcher.Invoke(priority: Windows.Threading.DispatcherPriority, method: Delegate) : obj
Windows.Threading.Dispatcher.Invoke(method: Delegate, timeout: TimeSpan, args: obj []) : obj
Windows.Threading.Dispatcher.Invoke(method: Delegate, priority: Windows.Threading.DispatcherPriority, args: obj []) : obj
Windows.Threading.Dispatcher.Invoke(priority: Windows.Threading.DispatcherPriority, timeout: TimeSpan, method: Delegate) : obj
Windows.Threading.Dispatcher.Invoke(priority: Windows.Threading.DispatcherPriority, method: Delegate, arg: obj) : obj
Windows.Threading.Dispatcher.Invoke(method: Delegate, timeout: TimeSpan, priority: Windows.Threading.DispatcherPriority, args: obj []) : obj
Windows.Threading.Dispatcher.Invoke(priority: Windows.Threading.DispatcherPriority, timeout: TimeSpan, method: Delegate, arg: obj) : obj
Windows.Threading.Dispatcher.Invoke(priority: Windows.Threading.DispatcherPriority, method: Delegate, arg: obj, args: obj []) : obj
Windows.Threading.Dispatcher.Invoke(priority: Windows.Threading.DispatcherPriority, timeout: TimeSpan, method: Delegate, arg: obj, args: obj []) : obj
Multiple items
type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15,'T16> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 * 'T15 * 'T16 -> unit

Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>

  type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15,'T16>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 * 'T15 -> unit

Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>

  type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 -> unit

Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_,_,_>

  type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 -> unit

Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_,_>

  type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 -> unit

Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_>

  type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 -> unit

Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_>

  type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 -> unit

Full name: System.Action<_,_,_,_,_,_,_,_,_,_>

  type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 -> unit

Full name: System.Action<_,_,_,_,_,_,_,_,_>

  type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 -> unit

Full name: System.Action<_,_,_,_,_,_,_,_>

  type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 -> unit

Full name: System.Action<_,_,_,_,_,_,_>

  type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2,'T3,'T4,'T5,'T6> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 -> unit

Full name: System.Action<_,_,_,_,_,_>

  type: Action<'T1,'T2,'T3,'T4,'T5,'T6>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2,'T3,'T4,'T5> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 -> unit

Full name: System.Action<_,_,_,_,_>

  type: Action<'T1,'T2,'T3,'T4,'T5>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2,'T3,'T4> =
  delegate of 'T1 * 'T2 * 'T3 * 'T4 -> unit

Full name: System.Action<_,_,_,_>

  type: Action<'T1,'T2,'T3,'T4>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2,'T3> =
  delegate of 'T1 * 'T2 * 'T3 -> unit

Full name: System.Action<_,_,_>

  type: Action<'T1,'T2,'T3>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T1,'T2> =
  delegate of 'T1 * 'T2 -> unit

Full name: System.Action<_,_>

  type: Action<'T1,'T2>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action<'T> =
  delegate of 'T -> unit

Full name: System.Action<_>

  type: Action<'T>
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

type Action =
  delegate of unit -> unit

Full name: System.Action

  type: Action
  implements: ICloneable
  implements: Runtime.Serialization.ISerializable
  inherits: MulticastDelegate
  inherits: Delegate


--------------------

Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> 'T13 -> 'T14 -> 'T15 -> 'T16 -> unit)

--------------------

Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> 'T13 -> 'T14 -> 'T15 -> unit)

--------------------

Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> 'T13 -> 'T14 -> unit)

--------------------

Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> 'T13 -> unit)

--------------------

Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> unit)

--------------------

Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> unit)

--------------------

Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> unit)

--------------------

Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> unit)

--------------------

Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> unit)

--------------------

Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> unit)

--------------------

Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> unit)

--------------------

Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> unit)

--------------------

Action('T1 -> 'T2 -> 'T3 -> 'T4 -> unit)

--------------------

Action('T1 -> 'T2 -> 'T3 -> unit)

--------------------

Action('T1 -> 'T2 -> unit)

--------------------

Action('T -> unit)

--------------------

Action(unit -> unit)
member Event.Trigger : arg:'T -> unit
val ignore : 'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
val loadNyseDataEvt : Event<StockDataCollection>
type StockDataCollection =
  class
    inherit Collections.ObjectModel.ReadOnlyCollection<StockData>
    new : data:Collections.Generic.IList<StockData> -> StockDataCollection
  end

Full name: Microsoft.Practices.ParallelGuideSamples.ADash.BusinessObjects.StockDataCollection

  type: StockDataCollection
  implements: Collections.Generic.IList<StockData>
  implements: Collections.Generic.ICollection<StockData>
  implements: seq<StockData>
  implements: Collections.IList
  implements: Collections.ICollection
  implements: Collections.IEnumerable
  inherits: Collections.ObjectModel.ReadOnlyCollection<StockData>


A data set with time series price information for various financial assets
val compareModelsEvt : Event<MarketRecommendation option>
type MarketRecommendation =
  class
    new : recommendation:string -> MarketRecommendation
    member Value : string
  end

Full name: Microsoft.Practices.ParallelGuideSamples.ADash.BusinessObjects.MarketRecommendation
type 'T option = Option<'T>

Full name: Microsoft.FSharp.Core.option<_>

  type: 'T option
  implements: Collections.IStructuralEquatable
  implements: IComparable<Option<'T>>
  implements: IComparable
  implements: Collections.IStructuralComparable
val errorHandlerEvt : Event<unit>
type unit = Unit

Full name: Microsoft.FSharp.Core.unit

  type: unit
  implements: IComparable
let loadNasdaqDataEvt = new Event<StockDataCollection>()
let mergeMarketDataEvt = new Event<StockDataCollection>()
let normalizeMarketDataEvt = new Event<StockDataCollection>()
let loadFedHistoricalDataEvt = new Event<StockDataCollection>()
let normalizeHistoricalDataEvt = new Event<StockDataCollection>()
let analyzeMarketDataEvt = new Event<StockAnalysisCollection>()
let analyzeHistoricalDataEvt = new Event<StockAnalysisCollection>()
let modelMarketDataEvt = new Event<MarketModel>()
let modelHistoricalDataEvt = new Event<MarketModel>()
abstract member AnalysisProcess.Start : unit -> unit

Full name: Untitled.AnalysisProcess.Start

Start the analysis (to be used after handlers are registered)
abstract member AnalysisProcess.TryCancel : unit -> unit

Full name: Untitled.AnalysisProcess.TryCancel

Try to cancel the process (if it has been already started)
val x : AnalysisProcess
member AnalysisProcess.LoadNyseData : IEvent<StockDataCollection>

Full name: Untitled.AnalysisProcess.LoadNyseData
property Event.Publish: IEvent<StockDataCollection>
member AnalysisProcess.CompareModels : IEvent<MarketRecommendation option>

Full name: Untitled.AnalysisProcess.CompareModels
property Event.Publish: IEvent<MarketRecommendation option>
member AnalysisProcess.ErrorHandler : IEvent<unit>

Full name: Untitled.AnalysisProcess.ErrorHandler
property Event.Publish: IEvent<unit>
member AnalysisProcess.TriggerLoadNyseData : v:StockDataCollection -> unit

Full name: Untitled.AnalysisProcess.TriggerLoadNyseData
val v : StockDataCollection

  type: StockDataCollection
  implements: Collections.Generic.IList<StockData>
  implements: Collections.Generic.ICollection<StockData>
  implements: seq<StockData>
  implements: Collections.IList
  implements: Collections.ICollection
  implements: Collections.IEnumerable
  inherits: Collections.ObjectModel.ReadOnlyCollection<StockData>
member AnalysisProcess.TriggerCompareModels : v:MarketRecommendation option -> unit

Full name: Untitled.AnalysisProcess.TriggerCompareModels
val v : MarketRecommendation option

  type: MarketRecommendation option
  implements: Collections.IStructuralEquatable
  implements: IComparable<Option<MarketRecommendation>>
  implements: IComparable
  implements: Collections.IStructuralComparable
member AnalysisProcess.TriggerErrorHandler : v:unit -> unit

Full name: Untitled.AnalysisProcess.TriggerErrorHandler
val v : unit

  type: unit
  implements: IComparable
member x.LoadNasdaqData = loadNasdaqDataEvt.Publish
member x.MergeMarketData = mergeMarketDataEvt.Publish
member x.NormalizeMarketData = normalizeMarketDataEvt.Publish
member x.LoadFedHistoricalData = loadFedHistoricalDataEvt.Publish
member x.NormalizeHistoricalData = normalizeHistoricalDataEvt.Publish
member x.AnalyzeMarketData = analyzeMarketDataEvt.Publish
member x.AnalyzeHistoricalData = analyzeHistoricalDataEvt.Publish
member x.ModelMarketData = modelMarketDataEvt.Publish
member x.ModelHistoricalData = modelHistoricalDataEvt.Publish

member x.TriggerLoadNasdaqData(v) = triggerGuiEvent loadNasdaqDataEvt v
member x.TriggerMergeMarketData(v) = triggerGuiEvent mergeMarketDataEvt v
member x.TriggerNormalizeMarketData(v) = triggerGuiEvent normalizeMarketDataEvt v
member x.TriggerLoadFedHistoricalData(v) = triggerGuiEvent loadFedHistoricalDataEvt v
member x.TriggerNormalizeHistoricalData(v) = triggerGuiEvent normalizeHistoricalDataEvt v
member x.TriggerAnalyzeMarketData(v) = triggerGuiEvent analyzeMarketDataEvt v
member x.TriggerAnalyzeHistoricalData(v) = triggerGuiEvent analyzeHistoricalDataEvt v
member x.TriggerModelMarketData(v) = triggerGuiEvent modelMarketDataEvt v
member x.TriggerModelHistoricalData(v) = triggerGuiEvent modelHistoricalDataEvt v
val sequentialAnalysis : (unit -> AnalysisProcess)
val engine : AnalysisProcess
abstract member AnalysisProcess.Start : unit -> unit

Start the analysis (to be used after handlers are registered)
Multiple items
type Task<'TResult> =
  class
    inherit System.Threading.Tasks.Task
    new : System.Func<'TResult> -> System.Threading.Tasks.Task<'TResult>
    new : System.Func<'TResult> * System.Threading.CancellationToken -> System.Threading.Tasks.Task<'TResult>
    new : System.Func<'TResult> * System.Threading.Tasks.TaskCreationOptions -> System.Threading.Tasks.Task<'TResult>
    new : System.Func<'TResult> * System.Threading.CancellationToken * System.Threading.Tasks.TaskCreationOptions -> System.Threading.Tasks.Task<'TResult>
    new : System.Func<obj,'TResult> * obj -> System.Threading.Tasks.Task<'TResult>
    new : System.Func<obj,'TResult> * obj * System.Threading.CancellationToken -> System.Threading.Tasks.Task<'TResult>
    new : System.Func<obj,'TResult> * obj * System.Threading.Tasks.TaskCreationOptions -> System.Threading.Tasks.Task<'TResult>
    new : System.Func<obj,'TResult> * obj * System.Threading.CancellationToken * System.Threading.Tasks.TaskCreationOptions -> System.Threading.Tasks.Task<'TResult>
    member ContinueWith : System.Action<System.Threading.Tasks.Task<'TResult>> -> System.Threading.Tasks.Task
    member ContinueWith<'TNewResult> : System.Func<System.Threading.Tasks.Task<'TResult>,'TNewResult> -> System.Threading.Tasks.Task<'TNewResult>
    member ContinueWith : System.Action<System.Threading.Tasks.Task<'TResult>> * System.Threading.CancellationToken -> System.Threading.Tasks.Task
    member ContinueWith : System.Action<System.Threading.Tasks.Task<'TResult>> * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task
    member ContinueWith : System.Action<System.Threading.Tasks.Task<'TResult>> * System.Threading.Tasks.TaskContinuationOptions -> System.Threading.Tasks.Task
    member ContinueWith<'TNewResult> : System.Func<System.Threading.Tasks.Task<'TResult>,'TNewResult> * System.Threading.CancellationToken -> System.Threading.Tasks.Task<'TNewResult>
    member ContinueWith<'TNewResult> : System.Func<System.Threading.Tasks.Task<'TResult>,'TNewResult> * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task<'TNewResult>
    member ContinueWith<'TNewResult> : System.Func<System.Threading.Tasks.Task<'TResult>,'TNewResult> * System.Threading.Tasks.TaskContinuationOptions -> System.Threading.Tasks.Task<'TNewResult>
    member ContinueWith : System.Action<System.Threading.Tasks.Task<'TResult>> * System.Threading.CancellationToken * System.Threading.Tasks.TaskContinuationOptions * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task
    member ContinueWith<'TNewResult> : System.Func<System.Threading.Tasks.Task<'TResult>,'TNewResult> * System.Threading.CancellationToken * System.Threading.Tasks.TaskContinuationOptions * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task<'TNewResult>
    member Result : 'TResult with get, set
    static member Factory : System.Threading.Tasks.TaskFactory<'TResult>
  end

Full name: System.Threading.Tasks.Task<_>

  type: Task<'TResult>
  implements: IThreadPoolWorkItem
  implements: IAsyncResult
  implements: IDisposable
  inherits: Task


--------------------

type Task =
  class
    new : System.Action -> System.Threading.Tasks.Task
    new : System.Action * System.Threading.CancellationToken -> System.Threading.Tasks.Task
    new : System.Action * System.Threading.Tasks.TaskCreationOptions -> System.Threading.Tasks.Task
    new : System.Action * System.Threading.CancellationToken * System.Threading.Tasks.TaskCreationOptions -> System.Threading.Tasks.Task
    new : System.Action<obj> * obj -> System.Threading.Tasks.Task
    new : System.Action<obj> * obj * System.Threading.CancellationToken -> System.Threading.Tasks.Task
    new : System.Action<obj> * obj * System.Threading.Tasks.TaskCreationOptions -> System.Threading.Tasks.Task
    new : System.Action<obj> * obj * System.Threading.CancellationToken * System.Threading.Tasks.TaskCreationOptions -> System.Threading.Tasks.Task
    member AsyncState : obj
    member ContinueWith : System.Action<System.Threading.Tasks.Task> -> System.Threading.Tasks.Task
    member ContinueWith<'TResult> : System.Func<System.Threading.Tasks.Task,'TResult> -> System.Threading.Tasks.Task<'TResult>
    member ContinueWith : System.Action<System.Threading.Tasks.Task> * System.Threading.CancellationToken -> System.Threading.Tasks.Task
    member ContinueWith : System.Action<System.Threading.Tasks.Task> * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task
    member ContinueWith : System.Action<System.Threading.Tasks.Task> * System.Threading.Tasks.TaskContinuationOptions -> System.Threading.Tasks.Task
    member ContinueWith<'TResult> : System.Func<System.Threading.Tasks.Task,'TResult> * System.Threading.CancellationToken -> System.Threading.Tasks.Task<'TResult>
    member ContinueWith<'TResult> : System.Func<System.Threading.Tasks.Task,'TResult> * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task<'TResult>
    member ContinueWith<'TResult> : System.Func<System.Threading.Tasks.Task,'TResult> * System.Threading.Tasks.TaskContinuationOptions -> System.Threading.Tasks.Task<'TResult>
    member ContinueWith : System.Action<System.Threading.Tasks.Task> * System.Threading.CancellationToken * System.Threading.Tasks.TaskContinuationOptions * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task
    member ContinueWith<'TResult> : System.Func<System.Threading.Tasks.Task,'TResult> * System.Threading.CancellationToken * System.Threading.Tasks.TaskContinuationOptions * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task<'TResult>
    member CreationOptions : System.Threading.Tasks.TaskCreationOptions
    member Dispose : unit -> unit
    member Exception : System.AggregateException
    member Id : int
    member IsCanceled : bool
    member IsCompleted : bool
    member IsFaulted : bool
    member RunSynchronously : unit -> unit
    member RunSynchronously : System.Threading.Tasks.TaskScheduler -> unit
    member Start : unit -> unit
    member Start : System.Threading.Tasks.TaskScheduler -> unit
    member Status : System.Threading.Tasks.TaskStatus
    member Wait : unit -> unit
    member Wait : System.TimeSpan -> bool
    member Wait : System.Threading.CancellationToken -> unit
    member Wait : int -> bool
    member Wait : int * System.Threading.CancellationToken -> bool
    static member CurrentId : System.Nullable<int>
    static member Factory : System.Threading.Tasks.TaskFactory
    static member WaitAll : System.Threading.Tasks.Task [] -> unit
    static member WaitAll : System.Threading.Tasks.Task [] * System.TimeSpan -> bool
    static member WaitAll : System.Threading.Tasks.Task [] * int -> bool
    static member WaitAll : System.Threading.Tasks.Task [] * System.Threading.CancellationToken -> unit
    static member WaitAll : System.Threading.Tasks.Task [] * int * System.Threading.CancellationToken -> bool
    static member WaitAny : System.Threading.Tasks.Task [] -> int
    static member WaitAny : System.Threading.Tasks.Task [] * System.TimeSpan -> int
    static member WaitAny : System.Threading.Tasks.Task [] * System.Threading.CancellationToken -> int
    static member WaitAny : System.Threading.Tasks.Task [] * int -> int
    static member WaitAny : System.Threading.Tasks.Task [] * int * System.Threading.CancellationToken -> int
  end

Full name: System.Threading.Tasks.Task

  type: Task
  implements: IThreadPoolWorkItem
  implements: IAsyncResult
  implements: IDisposable
Multiple items
property Task.Factory: TaskFactory

--------------------

property Task.Factory: TaskFactory<'TResult>
Multiple items
TaskFactory.StartNew<'TResult>(function: Func<'TResult>) : Task<'TResult>
TaskFactory.StartNew(action: Action) : Task
TaskFactory.StartNew<'TResult>(function: Func<obj,'TResult>, state: obj) : Task<'TResult>
TaskFactory.StartNew<'TResult>(function: Func<'TResult>, creationOptions: TaskCreationOptions) : Task<'TResult>
TaskFactory.StartNew<'TResult>(function: Func<'TResult>, cancellationToken: CancellationToken) : Task<'TResult>
TaskFactory.StartNew(action: Action<obj>, state: obj) : Task
TaskFactory.StartNew(action: Action, creationOptions: TaskCreationOptions) : Task
TaskFactory.StartNew(action: Action, cancellationToken: CancellationToken) : Task
TaskFactory.StartNew<'TResult>(function: Func<obj,'TResult>, state: obj, creationOptions: TaskCreationOptions) : Task<'TResult>
TaskFactory.StartNew<'TResult>(function: Func<obj,'TResult>, state: obj, cancellationToken: CancellationToken) : Task<'TResult>
   (+6 other overloads)
--------------------

TaskFactory.StartNew(function: Func<'TResult>) : Task<'TResult>
TaskFactory.StartNew(function: Func<obj,'TResult>, state: obj) : Task<'TResult>
TaskFactory.StartNew(function: Func<'TResult>, creationOptions: TaskCreationOptions) : Task<'TResult>
TaskFactory.StartNew(function: Func<'TResult>, cancellationToken: CancellationToken) : Task<'TResult>
TaskFactory.StartNew(function: Func<obj,'TResult>, state: obj, creationOptions: TaskCreationOptions) : Task<'TResult>
TaskFactory.StartNew(function: Func<obj,'TResult>, state: obj, cancellationToken: CancellationToken) : Task<'TResult>
TaskFactory.StartNew(function: Func<'TResult>, cancellationToken: CancellationToken, creationOptions: TaskCreationOptions, scheduler: TaskScheduler) : Task<'TResult>
TaskFactory.StartNew(function: Func<obj,'TResult>, state: obj, cancellationToken: CancellationToken, creationOptions: TaskCreationOptions, scheduler: TaskScheduler) : Task<'TResult>
val analysis : (unit -> unit)
abstract member AnalysisProcess.TryCancel : unit -> unit

Try to cancel the process (if it has been already started)
// Load & process NYSE and NASDAQ data
let nyseData = loadNyseData()
engine.TriggerLoadNyseData(nyseData)
let nasdaqData = loadNasdaqData()
engine.TriggerLoadNasdaqData(nasdaqData)

let mergedMarketData = mergeMarketData [ nyseData; nasdaqData ]
engine.TriggerMergeMarketData(mergedMarketData)
let normalizedMarketData = normalizeData mergedMarketData
engine.TriggerNormalizeMarketData(normalizedMarketData)
let analyzedStockData = analyzeData normalizedMarketData
engine.TriggerAnalyzeMarketData(analyzedStockData)
            
// Load & process FED data
let fedHistoricalData = loadFedHistoricalData()
engine.TriggerLoadFedHistoricalData(fedHistoricalData)
let normalizedHistoricalData = normalizeData fedHistoricalData
engine.TriggerNormalizeHistoricalData(normalizedHistoricalData)
let analyzedHistoricalData = analyzeData normalizedHistoricalData
engine.TriggerAnalyzeHistoricalData(analyzedHistoricalData)
val modeledMarketData : MarketModel
val runModel : StockAnalysisCollection -> MarketModel

Full name: Microsoft.Practices.ParallelGuideSamples.ADash.AnalysisModule.runModel
val analyzedStockData : StockAnalysisCollection

  type: StockAnalysisCollection
  implements: IList<StockAnalysis>
  implements: ICollection<StockAnalysis>
  implements: seq<StockAnalysis>
  implements: Collections.IList
  implements: Collections.ICollection
  implements: Collections.IEnumerable
  inherits: Collections.ObjectModel.ReadOnlyCollection<StockAnalysis>
member AnalysisProcess.TriggerModelMarketData : v:MarketModel -> unit
val modeledHistoricalData : MarketModel
val analyzedHistoricalData : StockAnalysisCollection

  type: StockAnalysisCollection
  implements: IList<StockAnalysis>
  implements: ICollection<StockAnalysis>
  implements: seq<StockAnalysis>
  implements: Collections.IList
  implements: Collections.ICollection
  implements: Collections.IEnumerable
  inherits: Collections.ObjectModel.ReadOnlyCollection<StockAnalysis>
member AnalysisProcess.TriggerModelHistoricalData : v:MarketModel -> unit
val recommendation : MarketRecommendation
val compareModels : seq<MarketModel> -> MarketRecommendation

Full name: Microsoft.Practices.ParallelGuideSamples.ADash.AnalysisModule.compareModels
member AnalysisProcess.TriggerCompareModels : v:MarketRecommendation option -> unit
union case Option.Some: 'T -> Option<'T>
val asyncAnalysis : (unit -> AnalysisProcess)
val cts : CancellationTokenSource

  type: CancellationTokenSource
  implements: IDisposable
type CancellationTokenSource =
  class
    new : unit -> System.Threading.CancellationTokenSource
    member Cancel : unit -> unit
    member Cancel : bool -> unit
    member Dispose : unit -> unit
    member IsCancellationRequested : bool
    member Token : System.Threading.CancellationToken
    static member CreateLinkedTokenSource : System.Threading.CancellationToken [] -> System.Threading.CancellationTokenSource
    static member CreateLinkedTokenSource : System.Threading.CancellationToken * System.Threading.CancellationToken -> System.Threading.CancellationTokenSource
  end

Full name: System.Threading.CancellationTokenSource

  type: CancellationTokenSource
  implements: IDisposable
Multiple items
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>

--------------------

type Async
with
  static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
  static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
  static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
  static member AwaitTask : task:Task<'T> -> Async<'T>
  static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
  static member CancelDefaultToken : unit -> unit
  static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
  static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
  static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
  static member Ignore : computation:Async<'T> -> Async<unit>
  static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
  static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
  static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
  static member Sleep : millisecondsDueTime:int -> Async<unit>
  static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
  static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
  static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
  static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
  static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
  static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
  static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
  static member SwitchToNewThread : unit -> Async<unit>
  static member SwitchToThreadPool : unit -> Async<unit>
  static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
  static member CancellationToken : Async<CancellationToken>
  static member DefaultCancellationToken : CancellationToken
end

Full name: Microsoft.FSharp.Control.Async
static member Async.Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
val compare : Async<unit>
property CancellationTokenSource.Token: CancellationToken
Multiple overloads
CancellationTokenSource.Cancel() : unit
CancellationTokenSource.Cancel(throwOnFirstException: bool) : unit
val marketModel : Async<MarketModel>
async {
  // Start loading of data from two sources in background (both I/O
  // operations are perfomed asynchronously without blocking threads)
  let! nyse =
    asyncLoadNyseData()
    |> Async.WithResult engine.TriggerLoadNyseData |> Async.StartChild
  let! nasdaq =
    asyncLoadNasdaqData()
    |> Async.WithResult engine.TriggerLoadNasdaqData |> Async.StartChild
                
  // Wait for both tasks to complete and continue
  let! nyseData = nyse
  let! nasdaqData = nasdaq
  let merged = mergeMarketData [ nyseData; nasdaqData ]
  engine.TriggerMergeMarketData(merged)
                
  // Perform analysis of the merged data
  let! normalized = asyncNormalizeData merged
  engine.TriggerNormalizeMarketData(normalized)
  let! analyzed = asyncAnalyzeData normalized
  engine.TriggerAnalyzeMarketData(analyzed)
  let! res = asyncRunModel analyzed
  engine.TriggerModelMarketData(res)
  return res }
val historicalModel : Async<MarketModel>
async {
  // Obtain data asynchronously using non-blocking I/O
  let! fed = asyncLoadFedHistoricalData()
  engine.TriggerLoadFedHistoricalData(fed)

  // Perform CPU-intensive analysis of the data
  let! normalized = asyncNormalizeData fed
  engine.TriggerNormalizeHistoricalData(normalized)
  let! analyzed = asyncAnalyzeData normalized
  engine.TriggerAnalyzeHistoricalData(analyzed)
  let! res = asyncRunModel analyzed
  engine.TriggerModelHistoricalData(res)
  return res }
Async.TryCancelled
  (async {
    try
        let! models = Async.Parallel [ marketModel; historicalModel ]
        let res = compareModels models
        engine.TriggerCompareModels(Some res)
    with e ->
        engine.TriggerErrorHandler() },
    fun ce ->
        engine.TriggerCompareModels(None))
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val nyse : Async<StockDataCollection>
val asyncLoadNyseData : unit -> Async<StockDataCollection>

Full name: Microsoft.Practices.ParallelGuideSamples.ADash.AnalysisModule.asyncLoadNyseData
static member Async.WithResult : f:('a0 -> unit) -> a:Async<'a0> -> Async<'a0>
member AnalysisProcess.TriggerLoadNyseData : v:StockDataCollection -> unit
static member Async.StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
val nasdaq : Async<StockDataCollection>
val asyncLoadNasdaqData : unit -> Async<StockDataCollection>

Full name: Microsoft.Practices.ParallelGuideSamples.ADash.AnalysisModule.asyncLoadNasdaqData
member AnalysisProcess.TriggerLoadNasdaqData : v:StockDataCollection -> unit
// Wait for both tasks to complete and continue
let! nyseData = nyse
let! nasdaqData = nasdaq
let merged = mergeMarketData [ nyseData; nasdaqData ]
engine.TriggerMergeMarketData(merged)
                
// Perform analysis of the merged data
let! normalized = asyncNormalizeData merged
engine.TriggerNormalizeMarketData(normalized)
val analyzed : StockAnalysisCollection

  type: StockAnalysisCollection
  implements: IList<StockAnalysis>
  implements: ICollection<StockAnalysis>
  implements: seq<StockAnalysis>
  implements: Collections.IList
  implements: Collections.ICollection
  implements: Collections.IEnumerable
  inherits: Collections.ObjectModel.ReadOnlyCollection<StockAnalysis>
val asyncAnalyzeData : StockDataCollection -> Async<StockAnalysisCollection>

Full name: Microsoft.Practices.ParallelGuideSamples.ADash.AnalysisModule.asyncAnalyzeData
val normalized : StockDataCollection

  type: StockDataCollection
  implements: IList<StockData>
  implements: ICollection<StockData>
  implements: seq<StockData>
  implements: Collections.IList
  implements: Collections.ICollection
  implements: Collections.IEnumerable
  inherits: Collections.ObjectModel.ReadOnlyCollection<StockData>
member AnalysisProcess.TriggerAnalyzeMarketData : v:StockAnalysisCollection -> unit
val res : MarketModel
val asyncRunModel : StockAnalysisCollection -> Async<MarketModel>

Full name: Microsoft.Practices.ParallelGuideSamples.ADash.AnalysisModule.asyncRunModel
// Obtain data asynchronously using non-blocking I/O
let! fed = asyncLoadFedHistoricalData()
engine.TriggerLoadFedHistoricalData(fed)

// Perform CPU-intensive analysis of the data
let! normalized = asyncNormalizeData fed
engine.TriggerNormalizeHistoricalData(normalized)
member AnalysisProcess.TriggerAnalyzeHistoricalData : v:StockAnalysisCollection -> unit
static member Async.TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
val models : MarketModel []

  type: MarketModel []
  implements: ICloneable
  implements: Collections.IList
  implements: Collections.ICollection
  implements: Collections.IStructuralComparable
  implements: Collections.IStructuralEquatable
  implements: IList<MarketModel>
  implements: ICollection<MarketModel>
  implements: seq<MarketModel>
  implements: Collections.IEnumerable
  inherits: Array
static member Async.Parallel : computations:seq<Async<'T>> -> Async<'T []>
val res : MarketRecommendation
val e : exn

  type: exn
  implements: Runtime.Serialization.ISerializable
  implements: Runtime.InteropServices._Exception
member AnalysisProcess.TriggerErrorHandler : v:unit -> unit
val ce : OperationCanceledException

  type: OperationCanceledException
  implements: Runtime.Serialization.ISerializable
  implements: Runtime.InteropServices._Exception
  inherits: SystemException
  inherits: exn
union case Option.None: Option<'T>

Published: Wednesday, 27 October 2010, 11:13 AM
Author: Tomas Petricek
Typos: Send me a pull request!
Tags: functional, parallel, asynchronous, f#