Author: atsushi
Date: 2006-04-03 20:47:56 -0400 (Mon, 03 Apr 2006)
New Revision: 58993
Modified:
trunk/mcs/class/System/System.Net/ChangeLog
trunk/mcs/class/System/System.Net/WebClient.cs
Log:
2006-04-04 Atsushi Enomoto <[EMAIL PROTECTED]>
* WebClient.cs : added a bunch of async method support.
Modified: trunk/mcs/class/System/System.Net/ChangeLog
===================================================================
--- trunk/mcs/class/System/System.Net/ChangeLog 2006-04-04 00:45:46 UTC (rev
58992)
+++ trunk/mcs/class/System/System.Net/ChangeLog 2006-04-04 00:47:56 UTC (rev
58993)
@@ -1,3 +1,7 @@
+2006-04-04 Atsushi Enomoto <[EMAIL PROTECTED]>
+
+ * WebClient.cs : added a bunch of async method support.
+
2006-04-03 Chris Toshok <[EMAIL PROTECTED]>
* HttpWebResponse.cs (ContentEncoding): return "" if the header
Modified: trunk/mcs/class/System/System.Net/WebClient.cs
===================================================================
--- trunk/mcs/class/System/System.Net/WebClient.cs 2006-04-04 00:45:46 UTC
(rev 58992)
+++ trunk/mcs/class/System/System.Net/WebClient.cs 2006-04-04 00:47:56 UTC
(rev 58993)
@@ -4,8 +4,10 @@
// Authors:
// Lawrence Pit ([EMAIL PROTECTED])
// Gonzalo Paniagua Javier ([EMAIL PROTECTED])
+// Atsushi Enomoto ([EMAIL PROTECTED])
//
// (c) 2003 Ximian, Inc. (http://www.ximian.com)
+// (C) 2006 Novell, Inc. (http://www.novell.com)
//
//
@@ -36,11 +38,19 @@
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
+#if NET_2_0
+using System.Collections.Generic;
+using System.Threading;
+#endif
namespace System.Net
{
[ComVisible(true)]
- public sealed class WebClient : Component
+ public
+#if !NET_2_0
+ sealed
+#endif
+ class WebClient : Component
{
static readonly string urlEncodedCType =
"application/x-www-form-urlencoded";
static byte [] hexBytes;
@@ -50,8 +60,10 @@
Uri baseAddress;
string baseString;
NameValueCollection queryString;
+ bool isBusy;
#if NET_2_0
Encoding encoding = Encoding.Default;
+ IWebProxy proxy;
#endif
// Constructors
@@ -130,42 +142,69 @@
encoding = value;
}
}
+
+ public IWebProxy Proxy {
+ get { return proxy; }
+ set { proxy = value; }
+ }
#endif
+#if NET_2_0
+ public bool IsBusy {
+ get { return isBusy || wait_handles != null &&
wait_handles.Count > 0; }
+ }
+#else
+ bool IsBusy {
+ get { return isBusy; }
+ }
+#endif
+
// Methods
-
+
+ void CheckBusy ()
+ {
+ if (IsBusy)
+ throw new NotSupportedException ("WebClient
does not support conccurent I/O operations.");
+ }
+
+ void SetBusy ()
+ {
+ lock (this) {
+ CheckBusy ();
+ isBusy = true;
+ }
+ }
+
+ // DownloadData
+
public byte [] DownloadData (string address)
{
- return DownloadData (address, "GET");
+ return DownloadData (MakeUri (address));
}
#if NET_2_0
public
#endif
- byte [] DownloadData (Uri address, string method)
+ byte [] DownloadData (Uri address)
{
- WebRequest request = SetupRequest (address, method);
- request.Method = method;
+ try {
+ SetBusy ();
+ return DownloadDataCore (address);
+ } finally {
+ isBusy = false;
+ }
+ }
+
+ byte [] DownloadDataCore (Uri address)
+ {
+ WebRequest request = SetupRequest (address, "GET");
WebResponse response = request.GetResponse ();
Stream st = ProcessResponse (response);
return ReadAll (st, (int) response.ContentLength);
}
-#if NET_2_0
- public
-#endif
- byte [] DownloadData (string address, string method)
- {
- return DownloadData (MakeUri (address), method);
- }
+ // DownloadFile
-#if NET_2_0
- public byte [] DownloadData (Uri address)
- {
- return DownloadData (address, "GET");
- }
-#endif
-
public void DownloadFile (string address, string fileName)
{
DownloadFile (MakeUri (address), fileName);
@@ -176,6 +215,16 @@
#endif
void DownloadFile (Uri address, string fileName)
{
+ try {
+ SetBusy ();
+ DownloadFileCore (address, fileName);
+ } finally {
+ isBusy = false;
+ }
+ }
+
+ void DownloadFileCore (Uri address, string fileName)
+ {
WebRequest request = SetupRequest (address);
WebResponse response = request.GetResponse ();
Stream st = ProcessResponse (response);
@@ -191,7 +240,9 @@
f.Close ();
}
-
+
+ // OpenRead
+
public Stream OpenRead (string address)
{
return OpenRead (MakeUri (address));
@@ -202,14 +253,21 @@
#endif
Stream OpenRead (Uri address)
{
- WebRequest request = SetupRequest (address);
- WebResponse response = request.GetResponse ();
- return ProcessResponse (response);
+ try {
+ SetBusy ();
+ WebRequest request = SetupRequest (address);
+ WebResponse response = request.GetResponse ();
+ return ProcessResponse (response);
+ } finally {
+ isBusy = false;
+ }
}
-
+
+ // OpenWrite
+
public Stream OpenWrite (string address)
{
- return OpenWrite (address, "POST");
+ return OpenWrite (MakeUri (address));
}
public Stream OpenWrite (string address, string method)
@@ -220,15 +278,41 @@
#if NET_2_0
public
#endif
+ Stream OpenWrite (Uri address)
+ {
+ return OpenWrite (address, DetermineMethod (address));
+ }
+
+#if NET_2_0
+ public
+#endif
Stream OpenWrite (Uri address, string method)
{
- WebRequest request = SetupRequest (address, method);
- return request.GetRequestStream ();
+ try {
+ SetBusy ();
+ WebRequest request = SetupRequest (address,
method);
+ return request.GetRequestStream ();
+ } finally {
+ isBusy = false;
+ }
}
-
+
+ private string DetermineMethod (Uri address)
+ {
+ if (address == null)
+ throw new ArgumentNullException ("address");
+#if NET_2_0
+ if (address.Scheme == Uri.UriSchemeFtp)
+ return "RETR";
+#endif
+ return "POST";
+ }
+
+ // UploadData
+
public byte [] UploadData (string address, byte [] data)
{
- return UploadData (address, "POST", data);
+ return UploadData (MakeUri (address), data);
}
public byte [] UploadData (string address, string method, byte
[] data)
@@ -237,17 +321,28 @@
}
#if NET_2_0
- public byte [] UploadData (Uri address, byte [] data)
+ public
+#endif
+ byte [] UploadData (Uri address, byte [] data)
{
- return UploadData (address, "POST", data);
+ return UploadData (address, DetermineMethod (address),
data);
}
-#endif
#if NET_2_0
public
#endif
byte [] UploadData (Uri address, string method, byte [] data)
{
+ try {
+ SetBusy ();
+ return UploadDataCore (address, method, data);
+ } finally {
+ isBusy = false;
+ }
+ }
+
+ byte [] UploadDataCore (Uri address, string method, byte []
data)
+ {
if (data == null)
throw new ArgumentNullException ("data");
@@ -261,11 +356,21 @@
Stream st = ProcessResponse (response);
return ReadAll (st, (int) response.ContentLength);
}
-
+
+ // UploadFile
+
public byte [] UploadFile (string address, string fileName)
{
- return UploadFile (address, "POST", fileName);
+ return UploadFile (MakeUri (address), fileName);
}
+
+#if NET_2_0
+ public
+#endif
+ byte [] UploadFile (Uri address, string fileName)
+ {
+ return UploadFile (address, DetermineMethod (address),
fileName);
+ }
public byte [] UploadFile (string address, string method,
string fileName)
{
@@ -277,6 +382,16 @@
#endif
byte [] UploadFile (Uri address, string method, string fileName)
{
+ try {
+ SetBusy ();
+ return UploadFileCore (address, method,
fileName);
+ } finally {
+ isBusy = false;
+ }
+ }
+
+ byte [] UploadFileCore (Uri address, string method, string
fileName)
+ {
string fileCType = Headers ["Content-Type"];
if (fileCType != null) {
string lower = fileCType.ToLower ();
@@ -336,7 +451,7 @@
public byte[] UploadValues (string address, NameValueCollection
data)
{
- return UploadValues (address, "POST", data);
+ return UploadValues (MakeUri (address), data);
}
public byte[] UploadValues (string address, string method,
NameValueCollection data)
@@ -347,8 +462,26 @@
#if NET_2_0
public
#endif
+ byte[] UploadValues (Uri address, NameValueCollection data)
+ {
+ return UploadValues (address, DetermineMethod
(address), data);
+ }
+
+#if NET_2_0
+ public
+#endif
byte[] UploadValues (Uri uri, string method,
NameValueCollection data)
{
+ try {
+ SetBusy ();
+ return UploadValuesCore (uri, method, data);
+ } finally {
+ isBusy = false;
+ }
+ }
+
+ byte[] UploadValuesCore (Uri uri, string method,
NameValueCollection data)
+ {
if (data == null)
throw new ArgumentNullException ("data"); // MS
throws a nullref
@@ -393,21 +526,11 @@
return encoding.GetString (DownloadData (address));
}
- public string DownloadString (string address, string method)
- {
- return encoding.GetString (DownloadData (address,
method));
- }
-
public string DownloadString (Uri address)
{
return encoding.GetString (DownloadData (address));
}
- public string DownloadString (Uri address, string method)
- {
- return encoding.GetString (DownloadData (address,
method));
- }
-
public string UploadString (string address, string data)
{
byte [] resp = UploadData (address, encoding.GetBytes
(data));
@@ -431,6 +554,18 @@
byte [] resp = UploadData (address, method,
encoding.GetBytes (data));
return encoding.GetString (resp);
}
+
+ public event DownloadDataCompletedEventHandler
DownloadDataCompleted;
+ public event AsyncCompletedEventHandler DownloadFileCompleted;
+ public event DownloadProgressChangedEventHandler
DownloadProgressChanged;
+ public event DownloadStringCompletedEventHandler
DownloadStringCompleted;
+ public event OpenReadCompletedEventHandler OpenReadCompleted;
+ public event OpenWriteCompletedEventHandler OpenWriteCompleted;
+ public event UploadDataCompletedEventHandler
UploadDataCompleted;
+ public event UploadFileCompletedEventHandler
UploadFileCompleted;
+ public event UploadProgressChangedEventHandler
UploadProgressChanged;
+ public event UploadStringCompletedEventHandler
UploadStringCompleted;
+ public event UploadValuesCompletedEventHandler
UploadValuesCompleted;
#endif
Uri MakeUri (string path)
@@ -477,6 +612,10 @@
WebRequest SetupRequest (Uri uri)
{
WebRequest request = WebRequest.Create (uri);
+#if NET_2_0
+ if (Proxy != null)
+ request.Proxy = Proxy;
+#endif
request.Credentials = credentials;
// Special headers. These are properties of
HttpWebRequest.
@@ -620,6 +759,335 @@
}
}
}
+
+#if NET_2_0
+ List<RegisteredWaitHandle> wait_handles;
+
+ List<RegisteredWaitHandle> WaitHandles {
+ get {
+ if (wait_handles == null)
+ wait_handles = new
List<RegisteredWaitHandle> ();
+ return wait_handles;
+ }
+ }
+
+ [MonoTODO ("Is it enough to just unregister wait handles from
ThreadPool?")]
+ public void CancelAsync ()
+ {
+ if (wait_handles == null)
+ return;
+ lock (wait_handles) {
+ foreach (RegisteredWaitHandle handle in
wait_handles)
+ handle.Unregister (null);
+ wait_handles.Clear ();
+ }
+ }
+
+ // DownloadDataAsync
+
+ public void DownloadDataAsync (Uri uri)
+ {
+ DownloadDataAsync (uri, null);
+ }
+
+ public void DownloadDataAsync (Uri uri, object asyncState)
+ {
+ lock (this) {
+ CheckBusy ();
+
+ object [] cbArgs = new object [] {uri,
asyncState};
+ WaitOrTimerCallback cb = delegate (object
state, bool timedOut) {
+ object [] args = (object []) state;
+ byte [] data = timedOut ? null :
DownloadData ((Uri) args [0]);
+ OnDownloadDataCompleted (
+ new
DownloadDataCompletedEventArgs (data, null, timedOut, args [1]));
+ };
+ AutoResetEvent ev = new AutoResetEvent (true);
+ WaitHandles.Add
(ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ }
+ }
+
+ // DownloadFileAsync
+
+ public void DownloadFileAsync (Uri uri, string method)
+ {
+ DownloadFileAsync (uri, method, null);
+ }
+
+ public void DownloadFileAsync (Uri uri, string method, object
asyncState)
+ {
+ lock (this) {
+ CheckBusy ();
+
+ object [] cbArgs = new object [] {uri, method,
asyncState};
+ WaitOrTimerCallback cb = delegate (object
innerState, bool timedOut) {
+ object [] args = (object []) innerState;
+ if (!timedOut)
+ DownloadFile ((Uri) args [0],
(string) args [1]);
+ OnDownloadFileCompleted (
+ new AsyncCompletedEventArgs
(null, timedOut, args [2]));
+ };
+ AutoResetEvent ev = new AutoResetEvent (true);
+ WaitHandles.Add
(ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ }
+ }
+
+ // DownloadStringAsync
+
+ public void DownloadStringAsync (Uri uri)
+ {
+ DownloadStringAsync (uri, null);
+ }
+
+ public void DownloadStringAsync (Uri uri, object asyncState)
+ {
+ lock (this) {
+ CheckBusy ();
+
+ object [] cbArgs = new object [] {uri,
asyncState};
+ WaitOrTimerCallback cb = delegate (object
innerState, bool timedOut) {
+ object [] args = (object []) innerState;
+ string data = timedOut ? null :
DownloadString ((Uri) args [0]);
+ OnDownloadStringCompleted (
+ new
DownloadStringCompletedEventArgs (data, null, timedOut, args [1]));
+ };
+ AutoResetEvent ev = new AutoResetEvent (true);
+ WaitHandles.Add
(ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ }
+ }
+
+ // OpenReadAsync
+
+ public void OpenReadAsync (Uri uri)
+ {
+ OpenReadAsync (uri, null);
+ }
+
+ public void OpenReadAsync (Uri uri, object asyncState)
+ {
+ lock (this) {
+ CheckBusy ();
+
+ object [] cbArgs = new object [] {uri,
asyncState};
+ WaitOrTimerCallback cb = delegate (object
innerState, bool timedOut) {
+ object [] args = (object []) innerState;
+ Stream stream = timedOut ? null :
OpenRead ((Uri) args [0]);
+ OnOpenReadCompleted (
+ new OpenReadCompletedEventArgs
(stream, null, timedOut, args [1]));
+ };
+ AutoResetEvent ev = new AutoResetEvent (true);
+ WaitHandles.Add
(ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ }
+ }
+
+ // OpenWriteAsync
+
+ public void OpenWriteAsync (Uri uri)
+ {
+ OpenWriteAsync (uri, null);
+ }
+
+ public void OpenWriteAsync (Uri uri, string method)
+ {
+ OpenWriteAsync (uri, method, null);
+ }
+
+ public void OpenWriteAsync (Uri uri, string method, object
asyncState)
+ {
+ lock (this) {
+ CheckBusy ();
+
+ object [] cbArgs = new object [] {uri, method,
asyncState};
+ WaitOrTimerCallback cb = delegate (object
innerState, bool timedOut) {
+ object [] args = (object []) innerState;
+ Stream stream = timedOut ? null :
OpenWrite ((Uri) args [0], (string) args [1]);
+ OnOpenWriteCompleted (
+ new OpenWriteCompletedEventArgs
(stream, null, timedOut, args [2]));
+ };
+ AutoResetEvent ev = new AutoResetEvent (true);
+ WaitHandles.Add
(ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ }
+ }
+
+ // UploadDataAsync
+
+ public void UploadDataAsync (Uri uri, byte [] data)
+ {
+ UploadDataAsync (uri, null, data);
+ }
+
+ public void UploadDataAsync (Uri uri, string method, byte []
data)
+ {
+ UploadDataAsync (uri, method, data, null);
+ }
+
+ public void UploadDataAsync (Uri uri, string method, byte []
data, object asyncState)
+ {
+ lock (this) {
+ CheckBusy ();
+
+ object [] cbArgs = new object [] {uri, method,
data, asyncState};
+ WaitOrTimerCallback cb = delegate (object
innerState, bool timedOut) {
+ object [] args = (object []) innerState;
+ byte [] data = timedOut ? null :
UploadData ((Uri) args [0], (string) args [1], (byte []) args [2]);
+ OnUploadDataCompleted (
+ new
UploadDataCompletedEventArgs (data, null, timedOut, args [3]));
+ };
+ AutoResetEvent ev = new AutoResetEvent (true);
+ WaitHandles.Add
(ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ }
+ }
+
+ // UploadFileAsync
+
+ public void UploadFileAsync (Uri uri, string file)
+ {
+ UploadFileAsync (uri, null, file);
+ }
+
+ public void UploadFileAsync (Uri uri, string method, string
file)
+ {
+ UploadFileAsync (uri, method, file, null);
+ }
+
+ public void UploadFileAsync (Uri uri, string method, string
file, object asyncState)
+ {
+ lock (this) {
+ CheckBusy ();
+
+ object [] cbArgs = new object [] {uri, method,
file, asyncState};
+ WaitOrTimerCallback cb = delegate (object
innerState, bool timedOut) {
+ object [] args = (object []) innerState;
+ byte [] data = timedOut ? null :
UploadFile ((Uri) args [0], (string) args [1], (string) args [2]);
+ OnUploadFileCompleted (
+ new
UploadFileCompletedEventArgs (data, null, timedOut, args [3]));
+ };
+ AutoResetEvent ev = new AutoResetEvent (true);
+ WaitHandles.Add
(ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ }
+ }
+
+ // UploadStringAsync
+
+ public void UploadStringAsync (Uri uri, string data)
+ {
+ UploadStringAsync (uri, null, data);
+ }
+
+ public void UploadStringAsync (Uri uri, string method, string
data)
+ {
+ UploadStringAsync (uri, method, data, null);
+ }
+
+ public void UploadStringAsync (Uri uri, string method, string
data, object asyncState)
+ {
+ lock (this) {
+ CheckBusy ();
+
+ object [] cbArgs = new object [] {uri, method,
data, asyncState};
+ WaitOrTimerCallback cb = delegate (object
innerState, bool timedOut) {
+ object [] args = (object []) innerState;
+ string data = timedOut ? null :
UploadString ((Uri) args [0], (string) args [1], (string) args [2]);
+ OnUploadStringCompleted (
+ new
UploadStringCompletedEventArgs (data, null, timedOut, args [3]));
+ };
+ AutoResetEvent ev = new AutoResetEvent (true);
+ WaitHandles.Add
(ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ }
+ }
+
+ // UploadValuesAsync
+
+ public void UploadValuesAsync (Uri uri, NameValueCollection
values)
+ {
+ UploadValuesAsync (uri, null, values);
+ }
+
+ public void UploadValuesAsync (Uri uri, string method,
NameValueCollection values)
+ {
+ UploadValuesAsync (uri, method, values, null);
+ }
+
+ public void UploadValuesAsync (Uri uri, string method,
NameValueCollection values, object asyncState)
+ {
+ lock (this) {
+ CheckBusy ();
+
+ object [] cbArgs = new object [] {uri, method,
values, asyncState};
+ WaitOrTimerCallback cb = delegate (object
innerState, bool timedOut) {
+ object [] args = (object []) innerState;
+ byte [] data = timedOut ? null :
UploadValues ((Uri) args [0], (string) args [1], (NameValueCollection) args
[2]);
+ OnUploadValuesCompleted (
+ new
UploadValuesCompletedEventArgs (data, null, timedOut, args [3]));
+ };
+ AutoResetEvent ev = new AutoResetEvent (true);
+ WaitHandles.Add
(ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
+ }
+ }
+
+ protected virtual void OnDownloadDataCompleted (
+ DownloadDataCompletedEventArgs args)
+ {
+ if (DownloadDataCompleted != null)
+ DownloadDataCompleted (this, args);
+ }
+
+ protected virtual void OnDownloadFileCompleted (
+ AsyncCompletedEventArgs args)
+ {
+ if (DownloadFileCompleted != null)
+ DownloadFileCompleted (this, args);
+ }
+
+ protected virtual void OnDownloadStringCompleted (
+ DownloadStringCompletedEventArgs args)
+ {
+ if (DownloadStringCompleted != null)
+ DownloadStringCompleted (this, args);
+ }
+
+ protected virtual void OnOpenReadCompleted (
+ OpenReadCompletedEventArgs args)
+ {
+ if (OpenReadCompleted != null)
+ OpenReadCompleted (this, args);
+ }
+
+ protected virtual void OnOpenWriteCompleted (
+ OpenWriteCompletedEventArgs args)
+ {
+ if (OpenWriteCompleted != null)
+ OpenWriteCompleted (this, args);
+ }
+
+ protected virtual void OnUploadDataCompleted (
+ UploadDataCompletedEventArgs args)
+ {
+ if (UploadDataCompleted != null)
+ UploadDataCompleted (this, args);
+ }
+
+ protected virtual void OnUploadFileCompleted (
+ UploadFileCompletedEventArgs args)
+ {
+ if (UploadFileCompleted != null)
+ UploadFileCompleted (this, args);
+ }
+
+ protected virtual void OnUploadStringCompleted (
+ UploadStringCompletedEventArgs args)
+ {
+ if (UploadStringCompleted != null)
+ UploadStringCompleted (this, args);
+ }
+
+ protected virtual void OnUploadValuesCompleted (
+ UploadValuesCompletedEventArgs args)
+ {
+ if (UploadValuesCompleted != null)
+ UploadValuesCompleted (this, args);
+ }
+#endif
}
}
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches