Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbb67118

Browse files
mexxlatkin
authored andcommitted
Add WebClient extensions AsyncDownloadData and AsyncDownloadFile
commit f864ece1fbe57b62413a8a020c08bffd21b271c1Merge:816e96e 66074d1Author: latkin <latkin@microsoft.com>Date: Thu Dec 11 15:45:57 2014 -0800 Merge branch 'WebClient-Async-Extensions' ofhttps://git01.codeplex.com/forks/mexx24/visualfsharp into asynccommit 66074d1c16e786d25f88ab9525bd5bce9a08180aAuthor: Max Malook <community@malook.de>Date: Thu Dec 4 11:57:44 2014 +0100 minor adjustments from code reviewcommit b6d7917b3b97d177e0040f920d2386dfaaf9e6f4Author: Max Malook <community@malook.de>Date: Tue Oct 28 23:25:37 2014 +0100 add tests for AsyncDownloadData and AsyncDownloadFile methodscommit 0dfdaa90cbcbc82e59bed59b91fbe1089a8c8fc5Author: Max Malook <community@malook.de>Date: Tue Oct 28 23:18:07 2014 +0100 introduce help method to remove code duplicationcommit 715061351cacbba833ac131912c4bb5e8540d7a9Author: Max Malook <community@malook.de>Date: Tue Oct 28 22:55:14 2014 +0100 add new methods to surface areacommit 185342059e99b66f4814f6f7694f178d90a4f000Author: Max Malook <community@malook.de>Date: Sun Oct 12 11:53:57 2014 +0200 add extension methods AsyncDownloadData and AsyncDownloadFile
1 parent816e96e commitbb67118

File tree

4 files changed

+142
-20
lines changed

4 files changed

+142
-20
lines changed

‎src/fsharp/FSharp.Core.Unittests/SurfaceArea.4.0.fs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,8 @@ Microsoft.FSharp.Control.ObservableModule: System.Type GetType()
725725
Microsoft.FSharp.Control.ObservableModule: Void Add[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], System.IObservable`1[T])
726726
Microsoft.FSharp.Control.WebExtensions: Boolean Equals(System.Object)
727727
Microsoft.FSharp.Control.WebExtensions: Int32 GetHashCode()
728+
Microsoft.FSharp.Control.WebExtensions: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] AsyncDownloadFile(System.Net.WebClient, System.Uri, System.String)
729+
Microsoft.FSharp.Control.WebExtensions: Microsoft.FSharp.Control.FSharpAsync`1[System.Byte[]] AsyncDownloadData(System.Net.WebClient, System.Uri)
728730
Microsoft.FSharp.Control.WebExtensions: Microsoft.FSharp.Control.FSharpAsync`1[System.Net.WebResponse] AsyncGetResponse(System.Net.WebRequest)
729731
Microsoft.FSharp.Control.WebExtensions: Microsoft.FSharp.Control.FSharpAsync`1[System.String] AsyncDownloadString(System.Net.WebClient, System.Uri)
730732
Microsoft.FSharp.Control.WebExtensions: System.String ToString()

‎src/fsharp/FSharp.Core/control.fs‎

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2129,29 +2129,56 @@ namespace Microsoft.FSharp.Control
21292129
#else
21302130

21312131
typeSystem.Net.WebClientwith
2132-
[<CompiledName("AsyncDownloadString")>]// give the extension member a 'nice', unmangled compiled name, unique within this module
2133-
memberthis.AsyncDownloadString(address:Uri):Async<string>=
2132+
member inlineprivatethis.Download(event:IEvent<'T,_>,handler:_->'T,start,result)=
21342133
letdownloadAsync=
21352134
Async.FromContinuations(fun(cont,econt,ccont)->
2136-
letuserToken=new obj()
2137-
let rechandler=
2138-
System.Net.DownloadStringCompletedEventHandler(fun _ args->
2139-
if userToken= args.UserStatethen
2140-
this.DownloadStringCompleted.RemoveHandler(handler)
2141-
if args.Cancelledthen
2142-
ccont(new OperationCanceledException())
2143-
elif args.Error<>nullthen
2144-
econt args.Error
2145-
else
2146-
cont args.Result)
2147-
this.DownloadStringCompleted.AddHandler(handler)
2148-
this.DownloadStringAsync(address, userToken)
2149-
)
2135+
letuserToken=new obj()
2136+
let recdelegate'(_:obj)(args:#ComponentModel.AsyncCompletedEventArgs)=
2137+
// ensure we handle the completed event from correct download call
2138+
if userToken= args.UserStatethen
2139+
event.RemoveHandler handle
2140+
if args.Cancelledthen
2141+
ccont(new OperationCanceledException())
2142+
elif args.Error<>nullthen
2143+
econt args.Error
2144+
else
2145+
cont(result args)
2146+
and handle= handler delegate'
2147+
event.AddHandler handle
2148+
start userToken
2149+
)
21502150

2151-
async{
2151+
async{
21522152
use! _holder= Async.OnCancel(fun _-> this.CancelAsync())
21532153
return! downloadAsync
21542154
}
2155+
2156+
[<CompiledName("AsyncDownloadString")>]// give the extension member a 'nice', unmangled compiled name, unique within this module
2157+
memberthis.AsyncDownloadString(address:Uri):Async<string>=
2158+
this.Download(
2159+
event= this.DownloadStringCompleted,
2160+
handler=(fun action-> Net.DownloadStringCompletedEventHandler(action)),
2161+
start=(fun userToken-> this.DownloadStringAsync(address, userToken)),
2162+
result=(fun args-> args.Result)
2163+
)
2164+
2165+
[<CompiledName("AsyncDownloadData")>]// give the extension member a 'nice', unmangled compiled name, unique within this module
2166+
memberthis.AsyncDownloadData(address:Uri):Async<byte[]>=
2167+
this.Download(
2168+
event= this.DownloadDataCompleted,
2169+
handler=(fun action-> Net.DownloadDataCompletedEventHandler(action)),
2170+
start=(fun userToken-> this.DownloadDataAsync(address, userToken)),
2171+
result=(fun args-> args.Result)
2172+
)
2173+
2174+
[<CompiledName("AsyncDownloadFile")>]// give the extension member a 'nice', unmangled compiled name, unique within this module
2175+
memberthis.AsyncDownloadFile(address:Uri,fileName:string):Async<unit>=
2176+
this.Download(
2177+
event= this.DownloadFileCompleted,
2178+
handler=(fun action-> ComponentModel.AsyncCompletedEventHandler(action)),
2179+
start=(fun userToken-> this.DownloadFileAsync(address, fileName, userToken)),
2180+
result=(fun _->())
2181+
)
21552182
#endif
21562183

21572184

‎src/fsharp/FSharp.Core/control.fsi‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,17 @@ namespace Microsoft.FSharp.Control
726726
/// <returns>An asynchronous computation that will wait for the download of the URI.</returns>
727727
[<CompiledName("AsyncDownloadString")>]// give the extension member a nice, unmangled compiled name, unique within this module
728728
memberAsyncDownloadString:address:System.Uri->Async<string>
729+
/// <summary>Returns an asynchronous computation that, when run, will wait for the download of the given URI.</summary>
730+
/// <param name="address">The URI to retrieve.</param>
731+
/// <returns>An asynchronous computation that will wait for the download of the URI.</returns>
732+
[<CompiledName("AsyncDownloadData")>]// give the extension member a nice, unmangled compiled name, unique within this module
733+
memberAsyncDownloadData:address:System.Uri->Async<byte[]>
734+
/// <summary>Returns an asynchronous computation that, when run, will wait for the download of the given URI to specified file.</summary>
735+
/// <param name="address">The URI to retrieve.</param>
736+
/// <param name="fileName">The filename to save download to.</param>
737+
/// <returns>An asynchronous computation that will wait for the download of the URI to specified file.</returns>
738+
[<CompiledName("AsyncDownloadFile")>]// give the extension member a nice, unmangled compiled name, unique within this module
739+
memberAsyncDownloadFile:address:System.Uri* fileName: string-> Async<unit>
729740
#endif
730741

731742
end

‎tests/fsharp/core/controlWebExt/test.fsx‎

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ module WebClientTests =
111111
//and one bad URL, so we know we work under both conditions. The aim of the tests is to get coverage
112112
//for cancellation logic paths � we count the number of request routines that have successfully entered
113113
//a try/finally that increments/decrements a counter. We check that the counter is zero at the end.
114-
letrepeatedFetchAndCancelTest()=
114+
letrepeatedFetchStringAndCancelTest()=
115115
printfn"starting requests and cancellation routines..."
116116
letactive= ref0
117117
for i=0to100do
@@ -143,9 +143,91 @@ module WebClientTests =
143143
System.Threading.Thread.Sleep(!wait*3)
144144

145145
printfn"final: active =%d"!active
146-
check"WebClient cancellation test final result"!active0
146+
check"WebClient.AsyncDownloadString cancellation test final result"!active0
147147

148-
repeatedFetchAndCancelTest()
148+
//This test starts ~600 web requests plus routines to cancel them. The tests are robust
149+
//to whether there is a web connection or not � we just catch all exceptions, and use one good URL
150+
//and one bad URL, so we know we work under both conditions. The aim of the tests is to get coverage
151+
//for cancellation logic paths � we count the number of request routines that have successfully entered
152+
//a try/finally that increments/decrements a counter. We check that the counter is zero at the end.
153+
letrepeatedFetchDataAndCancelTest()=
154+
printfn"starting requests and cancellation routines..."
155+
letactive= ref0
156+
for i=0to100do
157+
for sleepin[0;2;10]do
158+
for urlin["http://www.live.com";"http://www.badnonexistenturl-da-da-da-da-da.com"]do
159+
letcts=new CancellationTokenSource()
160+
letresult= ref0
161+
162+
Async.Start(async{letincremented= reffalse
163+
try
164+
try
165+
lock active(fun()-> incr active; incremented:=true)
166+
letc=new System.Net.WebClient()
167+
let!p1= c.AsyncDownloadData(System.Uri(url))
168+
let!p2= c.AsyncDownloadData(System.Uri(url))
169+
result:= p1.Length+ p2.Length
170+
finally
171+
lock active(fun()->if!incrementedthen decr active)
172+
with_->
173+
return()}, cancellationToken=cts.Token)
174+
175+
System.Threading.Thread.Sleep(sleep)
176+
Async.Start(async{do! Async.Sleep(100)
177+
cts.Cancel()})
178+
letwait= ref0
179+
while!active<>0&&!wait<500do
180+
incr wait
181+
printfn"final: active =%d, waiting%d"!active(!wait*3)
182+
System.Threading.Thread.Sleep(!wait*3)
183+
184+
printfn"final: active =%d"!active
185+
check"WebClient.AsyncDownloadData cancellation test final result"!active0
186+
187+
//This test starts ~600 web requests plus routines to cancel them. The tests are robust
188+
//to whether there is a web connection or not � we just catch all exceptions, and use one good URL
189+
//and one bad URL, so we know we work under both conditions. The aim of the tests is to get coverage
190+
//for cancellation logic paths � we count the number of request routines that have successfully entered
191+
//a try/finally that increments/decrements a counter. We check that the counter is zero at the end.
192+
letrepeatedFetchFileAndCancelTest()=
193+
printfn"starting requests and cancellation routines..."
194+
letactive= ref0
195+
for i=0to100do
196+
for sleepin[0;2;10]do
197+
for urlin["http://www.live.com";"http://www.badnonexistenturl-da-da-da-da-da.com"]do
198+
letcts=new CancellationTokenSource()
199+
200+
Async.Start(async{letincremented= reffalse
201+
try
202+
letp1= sprintf"%i_%i_p1.data" i sleep
203+
letp2= sprintf"%i_%i_p2.data" i sleep
204+
try
205+
lock active(fun()-> incr active; incremented:=true)
206+
letc=new System.Net.WebClient()
207+
do! c.AsyncDownloadFile(System.Uri(url), p1)
208+
do! c.AsyncDownloadFile(System.Uri(url), p2)
209+
finally
210+
lock active(fun()->if!incrementedthen decr active)
211+
System.IO.File.Delete(p1)
212+
System.IO.File.Delete(p2)
213+
with_->
214+
return()}, cancellationToken=cts.Token)
215+
216+
System.Threading.Thread.Sleep(sleep)
217+
Async.Start(async{do! Async.Sleep(100)
218+
cts.Cancel()})
219+
letwait= ref0
220+
while!active<>0&&!wait<500do
221+
incr wait
222+
printfn"final: active =%d, waiting%d"!active(!wait*3)
223+
System.Threading.Thread.Sleep(!wait*3)
224+
225+
printfn"final: active =%d"!active
226+
check"WebClient.AsyncDownloadFile cancellation test final result"!active0
227+
228+
repeatedFetchStringAndCancelTest()
229+
repeatedFetchDataAndCancelTest()
230+
repeatedFetchFileAndCancelTest()
149231

150232

151233
let_=

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp