Skip to content

Instantly share code, notes, and snippets.

@v2m
Created October 13, 2014 05:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save v2m/4821441c7faed21b0fde to your computer and use it in GitHub Desktop.
Save v2m/4821441c7faed21b0fde to your computer and use it in GitHub Desktop.
type System.Net.WebClient with
member inline internal this.DownloadWithWebClient(addHandler, removeHandler, extract, start) =
let downloadAsync =
Async.FromContinuations (fun (cont, econt, ccont) ->
let userToken = new obj()
let rec handler (_: obj) (args: 'T :> ComponentModel.AsyncCompletedEventArgs) =
if userToken = args.UserState then
removeHandler handle
if args.Cancelled then
ccont (new OperationCanceledException())
elif args.Error <> null then
econt args.Error
else
cont (extract args)
and handle = addHandler handler
start userToken
)
async {
use! _holder = Async.OnCancel(fun _ -> this.CancelAsync())
return! downloadAsync
}
[<CompiledName("AsyncDownloadString")>] // give the extension member a 'nice', unmangled compiled name, unique within this module
member this.AsyncDownloadString (address:Uri) : Async<string> =
this.DownloadWithWebClient(
addHandler = (fun handler ->
let d = Net.DownloadStringCompletedEventHandler(handler)
this.DownloadStringCompleted.AddHandler(d)
d),
removeHandler = (fun d -> this.DownloadStringCompleted.RemoveHandler d),
extract = (fun args -> args.Result),
start = (fun userToken-> this.DownloadStringAsync(address, userToken))
)
[<CompiledName("AsyncDownloadFile")>] // give the extension member a 'nice', unmangled compiled name, unique within this module
member this.AsyncDownloadFile (address:Uri) (fileName: string) : Async<unit> =
this.DownloadWithWebClient(
addHandler = (fun handler ->
let d = ComponentModel.AsyncCompletedEventHandler(handler)
this.DownloadFileCompleted.AddHandler(d)
d),
removeHandler = (fun d -> this.DownloadFileCompleted.RemoveHandler d),
extract = (fun _ -> ()),
start = (fun userToken -> this.DownloadFileAsync(address, fileName, userToken))
)
[<CompiledName("AsyncDownloadData")>] // give the extension member a 'nice', unmangled compiled name, unique within this module
member this.AsyncDownloadData (address:Uri) : Async<byte[]> =
this.DownloadWithWebClient(
addHandler = (fun handler ->
let d = Net.DownloadDataCompletedEventHandler(handler)
this.DownloadDataCompleted.AddHandler(d)
d),
removeHandler = (fun d -> this.DownloadDataCompleted.RemoveHandler d),
extract = (fun args -> args.Result),
start = (fun userToken -> this.DownloadDataAsync(address, userToken))
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment