5 people like it.

Walkthrough: Creating an Asynchronous HTTP Handler

The Microsoft tutorial Walkthrough: Creating an Asynchronous HTTP Handler did not describe how to use IHttpAsyncHandler from F#.
It was also a bit complicated, because it did not show how to do it from Visual Studio. Here is the Visual Studio F# version. 1. Create empty ASP.NET Web Application. Call it FSharpHttpAsyncHandler. 2. Add a F# library project to the solution. Call it FSharpHttpAsyncHandler.Lib. 3. Add the following code to Library1.fs in FSharpHttpAsyncHandler.Lib 4. Add a reference to System.Web in FSharpHttpAsyncHandler.Lib 5. Add a reference to FSharpHttpAsyncHandler.Lib in FSharpHttpAsyncHandler. 6. Add the following to Web.config in FSharpHttpAsyncHandler. 7. In the Web tab of the project properties of FSharpHttpAsyncHandler, set Start url to http://localhost://whatever.SampleAsync 8. Run debug.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
66: 
67: 
68: 
69: 
70: 
71: 
72: 
73: 
// Library1.fs content
namespace FSharpHttpAsyncHandler.Lib

open System
open System.Web
open System.Threading

type AsynchOperation (callback:AsyncCallback, context:HttpContext,  state:Object) as this =
    let _callback:AsyncCallback = callback
    let _context:HttpContext = context
    let _state:Object = state
    let mutable _completed:bool = false

    interface IAsyncResult with

        member x.IsCompleted
            with get() =
                _completed

        member x.AsyncWaitHandle
            with get() =
                null

        member x.AsyncState
            with get() =
                _state

        member x.CompletedSynchronously
            with get() =
                false

    member x.StartAsyncTask(workItemState:Object) :unit =
        _context.Response.Write("<p>Completion IsThreadPoolThread is " + (Thread.CurrentThread.IsThreadPoolThread).ToString() + "</p>\r\n")
        _context.Response.Write("Hello World from Async Handler!")
        _completed <- true
        _callback.Invoke(this:>IAsyncResult)

    member x.StartAsyncWork() =
        ThreadPool.QueueUserWorkItem(new WaitCallback(x.StartAsyncTask), null)

type HTTPAsyncHandler () =
    interface IHttpAsyncHandler with

        member x.IsReusable
            with get() = 
                false

        member x.BeginProcessRequest(context:HttpContext, cb:AsyncCallback, extraData:Object):IAsyncResult =
            context.Response.Write("<p>Begin IsThreadPoolThread is " + (Thread.CurrentThread.IsThreadPoolThread).ToString() + "</p>\r\n")
            let asynch:AsynchOperation = new AsynchOperation(cb, context, extraData)
            asynch.StartAsyncWork()|> ignore
            asynch:>IAsyncResult

        member x.ProcessRequest(context:HttpContext):unit =
            raise (new System.InvalidOperationException())

        member x.EndProcessRequest((result:IAsyncResult)):unit =
            ()
(* Web.config
<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true"/>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules runAllManagedModulesForAllRequests="true"/>
    <handlers>
      <add name="FunctionalHandler" preCondition="integratedMode" verb="*" path="*" type="FSharpHttpAsyncHandler.Lib.HTTPAsyncHandler, FSharpHttpAsyncHandler.Lib"/>
    </handlers>
  </system.webServer>
</configuration>     
*)
namespace System
namespace System.Web
namespace System.Threading
Multiple items
type AsynchOperation =
  interface IAsyncResult
  new : callback:AsyncCallback * context:HttpContext * state:Object -> AsynchOperation
  member StartAsyncTask : workItemState:Object -> unit
  member StartAsyncWork : unit -> bool

Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation

--------------------
new : callback:AsyncCallback * context:HttpContext * state:Object -> AsynchOperation
val callback : AsyncCallback
type AsyncCallback =
  delegate of IAsyncResult -> unit

Full name: System.AsyncCallback
val context : HttpContext
Multiple items
type HttpContext =
  new : wr:HttpWorkerRequest -> HttpContext + 1 overload
  member AddError : errorInfo:Exception -> unit
  member AllErrors : Exception[]
  member Application : HttpApplicationState
  member ApplicationInstance : HttpApplication with get, set
  member Cache : Cache
  member ClearError : unit -> unit
  member CurrentHandler : IHttpHandler
  member CurrentNotification : RequestNotification with get, set
  member Error : Exception
  ...

Full name: System.Web.HttpContext

--------------------
HttpContext(wr: HttpWorkerRequest) : unit
HttpContext(request: HttpRequest, response: HttpResponse) : unit
val state : Object
Multiple items
type Object =
  new : unit -> obj
  member Equals : obj:obj -> bool
  member GetHashCode : unit -> int
  member GetType : unit -> Type
  member ToString : unit -> string
  static member Equals : objA:obj * objB:obj -> bool
  static member ReferenceEquals : objA:obj * objB:obj -> bool

Full name: System.Object

--------------------
Object() : unit
val this : AsynchOperation
type bool = Boolean

Full name: Microsoft.FSharp.Core.bool
type IAsyncResult =
  member AsyncState : obj
  member AsyncWaitHandle : WaitHandle
  member CompletedSynchronously : bool
  member IsCompleted : bool

Full name: System.IAsyncResult
val x : AsynchOperation
override AsynchOperation.IsCompleted : bool

Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation.IsCompleted
val mutable _completed : bool
override AsynchOperation.AsyncWaitHandle : WaitHandle

Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation.AsyncWaitHandle
override AsynchOperation.AsyncState : obj

Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation.AsyncState
val _state : Object
override AsynchOperation.CompletedSynchronously : bool

Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation.CompletedSynchronously
member AsynchOperation.StartAsyncTask : workItemState:Object -> unit

Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation.StartAsyncTask
val workItemState : Object
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
val _context : HttpContext
property HttpContext.Response: HttpResponse
HttpResponse.Write(ch: char) : unit
HttpResponse.Write(obj: obj) : unit
HttpResponse.Write(s: string) : unit
HttpResponse.Write(buffer: char [], index: int, count: int) : unit
Multiple items
type Thread =
  inherit CriticalFinalizerObject
  new : start:ThreadStart -> Thread + 3 overloads
  member Abort : unit -> unit + 1 overload
  member ApartmentState : ApartmentState with get, set
  member CurrentCulture : CultureInfo with get, set
  member CurrentUICulture : CultureInfo with get, set
  member DisableComObjectEagerCleanup : unit -> unit
  member ExecutionContext : ExecutionContext
  member GetApartmentState : unit -> ApartmentState
  member GetCompressedStack : unit -> CompressedStack
  member GetHashCode : unit -> int
  ...

Full name: System.Threading.Thread

--------------------
Thread(start: ThreadStart) : unit
Thread(start: ParameterizedThreadStart) : unit
Thread(start: ThreadStart, maxStackSize: int) : unit
Thread(start: ParameterizedThreadStart, maxStackSize: int) : unit
property Thread.CurrentThread: Thread
property Thread.IsThreadPoolThread: bool
val _callback : AsyncCallback
AsyncCallback.Invoke(ar: IAsyncResult) : unit
member AsynchOperation.StartAsyncWork : unit -> bool

Full name: FSharpHttpAsyncHandler.Lib.AsynchOperation.StartAsyncWork
type ThreadPool =
  static member BindHandle : osHandle:nativeint -> bool + 1 overload
  static member GetAvailableThreads : workerThreads:int * completionPortThreads:int -> unit
  static member GetMaxThreads : workerThreads:int * completionPortThreads:int -> unit
  static member GetMinThreads : workerThreads:int * completionPortThreads:int -> unit
  static member QueueUserWorkItem : callBack:WaitCallback -> bool + 1 overload
  static member RegisterWaitForSingleObject : waitObject:WaitHandle * callBack:WaitOrTimerCallback * state:obj * millisecondsTimeOutInterval:uint32 * executeOnlyOnce:bool -> RegisteredWaitHandle + 3 overloads
  static member SetMaxThreads : workerThreads:int * completionPortThreads:int -> bool
  static member SetMinThreads : workerThreads:int * completionPortThreads:int -> bool
  static member UnsafeQueueNativeOverlapped : overlapped:NativeOverlapped -> bool
  static member UnsafeQueueUserWorkItem : callBack:WaitCallback * state:obj -> bool
  ...

Full name: System.Threading.ThreadPool
ThreadPool.QueueUserWorkItem(callBack: WaitCallback) : bool
ThreadPool.QueueUserWorkItem(callBack: WaitCallback, state: obj) : bool
type WaitCallback =
  delegate of obj -> unit

Full name: System.Threading.WaitCallback
member AsynchOperation.StartAsyncTask : workItemState:Object -> unit
Multiple items
type HTTPAsyncHandler =
  interface IHttpAsyncHandler
  new : unit -> HTTPAsyncHandler

Full name: FSharpHttpAsyncHandler.Lib.HTTPAsyncHandler

--------------------
new : unit -> HTTPAsyncHandler
type IHttpAsyncHandler =
  member BeginProcessRequest : context:HttpContext * cb:AsyncCallback * extraData:obj -> IAsyncResult
  member EndProcessRequest : result:IAsyncResult -> unit

Full name: System.Web.IHttpAsyncHandler
val x : HTTPAsyncHandler
override HTTPAsyncHandler.IsReusable : bool

Full name: FSharpHttpAsyncHandler.Lib.HTTPAsyncHandler.IsReusable
override HTTPAsyncHandler.BeginProcessRequest : context:HttpContext * cb:AsyncCallback * extraData:obj -> IAsyncResult

Full name: FSharpHttpAsyncHandler.Lib.HTTPAsyncHandler.BeginProcessRequest
val cb : AsyncCallback
val extraData : obj
val asynch : AsynchOperation
member AsynchOperation.StartAsyncWork : unit -> bool
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
override HTTPAsyncHandler.ProcessRequest : context:HttpContext -> unit

Full name: FSharpHttpAsyncHandler.Lib.HTTPAsyncHandler.ProcessRequest
val raise : exn:Exception -> 'T

Full name: Microsoft.FSharp.Core.Operators.raise
Multiple items
type InvalidOperationException =
  inherit SystemException
  new : unit -> InvalidOperationException + 2 overloads

Full name: System.InvalidOperationException

--------------------
InvalidOperationException() : unit
InvalidOperationException(message: string) : unit
InvalidOperationException(message: string, innerException: exn) : unit
override HTTPAsyncHandler.EndProcessRequest : result:IAsyncResult -> unit

Full name: FSharpHttpAsyncHandler.Lib.HTTPAsyncHandler.EndProcessRequest
val result : IAsyncResult

More information

Link:http://fssnip.net/7Ub
Posted:6 years ago
Author:Erling Hellenäs
Tags: asynchronous , http , sql server , threading