2 // System.Net.WebClient
5 // Lawrence Pit (loz@cable.a2000.nl)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // Atsushi Enomoto (atsushi@ximian.com)
9 // (c) 2003 Ximian, Inc. (http://www.ximian.com)
10 // (C) 2006 Novell, Inc. (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Collections.Specialized;
36 using System.ComponentModel;
38 using System.Runtime.InteropServices;
39 using System.Runtime.Serialization;
42 using System.Collections.Generic;
43 using System.Threading;
53 class WebClient : Component
55 static readonly string urlEncodedCType = "application/x-www-form-urlencoded";
56 static byte [] hexBytes;
57 ICredentials credentials;
58 WebHeaderCollection headers;
59 WebHeaderCollection responseHeaders;
62 NameValueCollection queryString;
65 Encoding encoding = Encoding.Default;
72 hexBytes = new byte [16];
74 for (int i = '0'; i <= '9'; i++, index++)
75 hexBytes [index] = (byte) i;
77 for (int i = 'A'; i <= 'F'; i++, index++)
78 hexBytes [index] = (byte) i;
87 public string BaseAddress {
89 if (baseString == null) {
90 if (baseAddress == null)
94 baseString = baseAddress.ToString ();
99 if (value == null || value == "") {
102 baseAddress = new Uri (value);
107 public ICredentials Credentials {
108 get { return credentials; }
109 set { credentials = value; }
112 public WebHeaderCollection Headers {
115 headers = new WebHeaderCollection ();
119 set { headers = value; }
122 public NameValueCollection QueryString {
124 if (queryString == null)
125 queryString = new NameValueCollection ();
129 set { queryString = value; }
132 public WebHeaderCollection ResponseHeaders {
133 get { return responseHeaders; }
137 public Encoding Encoding {
138 get { return encoding; }
141 throw new ArgumentNullException ("value");
146 public IWebProxy Proxy {
147 get { return proxy; }
148 set { proxy = value; }
154 get { return isBusy || wait_handles != null && wait_handles.Count > 0; }
158 get { return isBusy; }
167 throw new NotSupportedException ("WebClient does not support conccurent I/O operations.");
180 public byte [] DownloadData (string address)
182 return DownloadData (MakeUri (address));
188 byte [] DownloadData (Uri address)
192 return DownloadDataCore (address);
198 byte [] DownloadDataCore (Uri address)
200 WebRequest request = SetupRequest (address, "GET");
201 WebResponse response = request.GetResponse ();
202 Stream st = ProcessResponse (response);
203 return ReadAll (st, (int) response.ContentLength);
208 public void DownloadFile (string address, string fileName)
210 DownloadFile (MakeUri (address), fileName);
216 void DownloadFile (Uri address, string fileName)
220 DownloadFileCore (address, fileName);
226 void DownloadFileCore (Uri address, string fileName)
228 WebRequest request = SetupRequest (address);
229 WebResponse response = request.GetResponse ();
230 Stream st = ProcessResponse (response);
232 int cLength = (int) response.ContentLength;
233 int length = (cLength <= -1 || cLength > 8192) ? 8192 : cLength;
234 byte [] buffer = new byte [length];
235 FileStream f = new FileStream (fileName, FileMode.CreateNew);
238 while ((nread = st.Read (buffer, 0, length)) != 0)
239 f.Write (buffer, 0, nread);
246 public Stream OpenRead (string address)
248 return OpenRead (MakeUri (address));
254 Stream OpenRead (Uri address)
258 WebRequest request = SetupRequest (address);
259 WebResponse response = request.GetResponse ();
260 return ProcessResponse (response);
268 public Stream OpenWrite (string address)
270 return OpenWrite (MakeUri (address));
273 public Stream OpenWrite (string address, string method)
275 return OpenWrite (MakeUri (address), method);
281 Stream OpenWrite (Uri address)
283 return OpenWrite (address, DetermineMethod (address));
289 Stream OpenWrite (Uri address, string method)
293 WebRequest request = SetupRequest (address, method);
294 return request.GetRequestStream ();
300 private string DetermineMethod (Uri address)
303 throw new ArgumentNullException ("address");
305 if (address.Scheme == Uri.UriSchemeFtp)
313 public byte [] UploadData (string address, byte [] data)
315 return UploadData (MakeUri (address), data);
318 public byte [] UploadData (string address, string method, byte [] data)
320 return UploadData (MakeUri (address), method, data);
326 byte [] UploadData (Uri address, byte [] data)
328 return UploadData (address, DetermineMethod (address), data);
334 byte [] UploadData (Uri address, string method, byte [] data)
338 return UploadDataCore (address, method, data);
344 byte [] UploadDataCore (Uri address, string method, byte [] data)
347 throw new ArgumentNullException ("data");
349 int contentLength = data.Length;
350 WebRequest request = SetupRequest (address, method, contentLength);
351 using (Stream stream = request.GetRequestStream ()) {
352 stream.Write (data, 0, contentLength);
355 WebResponse response = request.GetResponse ();
356 Stream st = ProcessResponse (response);
357 return ReadAll (st, (int) response.ContentLength);
362 public byte [] UploadFile (string address, string fileName)
364 return UploadFile (MakeUri (address), fileName);
370 byte [] UploadFile (Uri address, string fileName)
372 return UploadFile (address, DetermineMethod (address), fileName);
375 public byte [] UploadFile (string address, string method, string fileName)
377 return UploadFile (MakeUri (address), method, fileName);
383 byte [] UploadFile (Uri address, string method, string fileName)
387 return UploadFileCore (address, method, fileName);
393 byte [] UploadFileCore (Uri address, string method, string fileName)
395 string fileCType = Headers ["Content-Type"];
396 if (fileCType != null) {
397 string lower = fileCType.ToLower ();
398 if (lower.StartsWith ("multipart/"))
399 throw new WebException ("Content-Type cannot be set to a multipart" +
400 " type for this request.");
402 fileCType = "application/octet-stream";
405 string boundary = "------------" + DateTime.Now.Ticks.ToString ("x");
406 Headers ["Content-Type"] = String.Format ("multipart/form-data; boundary={0}", boundary);
407 WebRequest request = SetupRequest (address, method);
408 Stream reqStream = null;
409 Stream fStream = null;
410 byte [] resultBytes = null;
413 fStream = File.OpenRead (fileName);
414 reqStream = request.GetRequestStream ();
415 byte [] realBoundary = Encoding.ASCII.GetBytes ("--" + boundary + "\r\n");
416 reqStream.Write (realBoundary, 0, realBoundary.Length);
417 string partHeaders = String.Format ("Content-Disposition: form-data; " +
418 "name=\"file\"; filename=\"{0}\"\r\n" +
419 "Content-Type: {1}\r\n\r\n",
420 Path.GetFileName (fileName), fileCType);
422 byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
423 reqStream.Write (partHeadersBytes, 0, partHeadersBytes.Length);
425 byte [] buffer = new byte [4096];
426 while ((nread = fStream.Read (buffer, 0, 4096)) != 0)
427 reqStream.Write (buffer, 0, nread);
429 reqStream.WriteByte ((byte) '\r');
430 reqStream.WriteByte ((byte) '\n');
431 reqStream.Write (realBoundary, 0, realBoundary.Length);
434 WebResponse response = request.GetResponse ();
435 Stream st = ProcessResponse (response);
436 resultBytes = ReadAll (st, (int) response.ContentLength);
437 } catch (WebException) {
439 } catch (Exception e) {
440 throw new WebException ("Error uploading file.", e);
445 if (reqStream != null)
452 public byte[] UploadValues (string address, NameValueCollection data)
454 return UploadValues (MakeUri (address), data);
457 public byte[] UploadValues (string address, string method, NameValueCollection data)
459 return UploadValues (MakeUri (address), method, data);
465 byte[] UploadValues (Uri address, NameValueCollection data)
467 return UploadValues (address, DetermineMethod (address), data);
473 byte[] UploadValues (Uri uri, string method, NameValueCollection data)
477 return UploadValuesCore (uri, method, data);
483 byte[] UploadValuesCore (Uri uri, string method, NameValueCollection data)
486 throw new ArgumentNullException ("data"); // MS throws a nullref
488 string cType = Headers ["Content-Type"];
489 if (cType != null && String.Compare (cType, urlEncodedCType, true) != 0)
490 throw new WebException ("Content-Type header cannot be changed from its default " +
491 "value for this request.");
493 Headers ["Content-Type"] = urlEncodedCType;
494 WebRequest request = SetupRequest (uri, method);
495 Stream rqStream = request.GetRequestStream ();
496 MemoryStream tmpStream = new MemoryStream ();
497 foreach (string key in data) {
498 byte [] bytes = Encoding.ASCII.GetBytes (key);
499 UrlEncodeAndWrite (tmpStream, bytes);
500 tmpStream.WriteByte ((byte) '=');
501 bytes = Encoding.ASCII.GetBytes (data [key]);
502 UrlEncodeAndWrite (tmpStream, bytes);
503 tmpStream.WriteByte ((byte) '&');
506 int length = (int) tmpStream.Length;
508 tmpStream.SetLength (--length); // remove trailing '&'
510 tmpStream.WriteByte ((byte) '\r');
511 tmpStream.WriteByte ((byte) '\n');
513 byte [] buf = tmpStream.GetBuffer ();
514 rqStream.Write (buf, 0, length + 2);
518 WebResponse response = request.GetResponse ();
519 Stream st = ProcessResponse (response);
520 return ReadAll (st, (int) response.ContentLength);
524 public string DownloadString (string address)
526 return encoding.GetString (DownloadData (address));
529 public string DownloadString (Uri address)
531 return encoding.GetString (DownloadData (address));
534 public string UploadString (string address, string data)
536 byte [] resp = UploadData (address, encoding.GetBytes (data));
537 return encoding.GetString (resp);
540 public string UploadString (string address, string method, string data)
542 byte [] resp = UploadData (address, method, encoding.GetBytes (data));
543 return encoding.GetString (resp);
546 public string UploadString (Uri address, string data)
548 byte [] resp = UploadData (address, encoding.GetBytes (data));
549 return encoding.GetString (resp);
552 public string UploadString (Uri address, string method, string data)
554 byte [] resp = UploadData (address, method, encoding.GetBytes (data));
555 return encoding.GetString (resp);
558 public event DownloadDataCompletedEventHandler DownloadDataCompleted;
559 public event AsyncCompletedEventHandler DownloadFileCompleted;
560 public event DownloadProgressChangedEventHandler DownloadProgressChanged;
561 public event DownloadStringCompletedEventHandler DownloadStringCompleted;
562 public event OpenReadCompletedEventHandler OpenReadCompleted;
563 public event OpenWriteCompletedEventHandler OpenWriteCompleted;
564 public event UploadDataCompletedEventHandler UploadDataCompleted;
565 public event UploadFileCompletedEventHandler UploadFileCompleted;
566 public event UploadProgressChangedEventHandler UploadProgressChanged;
567 public event UploadStringCompletedEventHandler UploadStringCompleted;
568 public event UploadValuesCompletedEventHandler UploadValuesCompleted;
571 Uri MakeUri (string path)
574 if (queryString != null && queryString.Count != 0) {
575 // This is not the same as UploadValues, because these 'keys' are not
577 StringBuilder sb = new StringBuilder ();
579 foreach (string key in queryString)
580 sb.AppendFormat ("{0}={1}&", key, UrlEncode (queryString [key]));
582 if (sb.Length != 0) {
583 sb.Length--; // remove trailing '&'
584 query = sb.ToString ();
589 if (baseAddress == null && query == null) {
591 return new Uri (path);
593 catch (System.UriFormatException) {
594 if ((path[0] == Path.DirectorySeparatorChar) || (path[1] == ':' && Char.ToLower(path[0]) > 'a' && Char.ToLower(path[0]) < 'z')) {
595 return new Uri ("file://" + path);
598 return new Uri ("file://" + Environment.CurrentDirectory + Path.DirectorySeparatorChar + path);
603 if (baseAddress == null)
604 return new Uri (path + query, (query != null));
607 return new Uri (baseAddress, path);
609 return new Uri (baseAddress, path + query, (query != null));
612 WebRequest SetupRequest (Uri uri)
614 WebRequest request = WebRequest.Create (uri);
617 request.Proxy = Proxy;
619 request.Credentials = credentials;
621 // Special headers. These are properties of HttpWebRequest.
622 // What do we do with other requests differnt from HttpWebRequest?
623 if (headers != null && headers.Count != 0 && (request is HttpWebRequest)) {
624 HttpWebRequest req = (HttpWebRequest) request;
625 string expect = headers ["Expect"];
626 string contentType = headers ["Content-Type"];
627 string accept = headers ["Accept"];
628 string connection = headers ["Connection"];
629 string userAgent = headers ["User-Agent"];
630 string referer = headers ["Referer"];
631 headers.RemoveInternal ("Expect");
632 headers.RemoveInternal ("Content-Type");
633 headers.RemoveInternal ("Accept");
634 headers.RemoveInternal ("Connection");
635 headers.RemoveInternal ("Referer");
636 headers.RemoveInternal ("User-Agent");
637 request.Headers = headers;
639 if (expect != null && expect != "")
642 if (accept != null && accept != "")
645 if (contentType != null && contentType != "")
646 req.ContentType = contentType;
648 if (connection != null && connection != "")
649 req.Connection = connection;
651 if (userAgent != null && userAgent != "")
652 req.UserAgent = userAgent;
654 if (referer != null && referer != "")
655 req.Referer = referer;
658 responseHeaders = null;
662 WebRequest SetupRequest (Uri uri, string method)
664 WebRequest request = SetupRequest (uri);
665 request.Method = method;
669 WebRequest SetupRequest (Uri uri, string method, int contentLength)
671 WebRequest request = SetupRequest (uri, method);
672 request.ContentLength = contentLength;
676 Stream ProcessResponse (WebResponse response)
678 responseHeaders = response.Headers;
679 return response.GetResponseStream ();
682 static byte [] ReadAll (Stream stream, int length)
684 MemoryStream ms = null;
686 bool nolength = (length == -1);
687 int size = ((nolength) ? 8192 : length);
689 ms = new MemoryStream ();
693 byte [] buffer = new byte [size];
694 while ((nread = stream.Read (buffer, offset, size)) != 0) {
696 ms.Write (buffer, 0, nread);
704 return ms.ToArray ();
709 string UrlEncode (string str)
711 StringBuilder result = new StringBuilder ();
713 int len = str.Length;
714 for (int i = 0; i < len; i++) {
718 else if ((c < '0' && c != '-' && c != '.') ||
719 (c < 'A' && c > '9') ||
720 (c > 'Z' && c < 'a' && c != '_') ||
723 int idx = ((int) c) >> 4;
724 result.Append ((char) hexBytes [idx]);
725 idx = ((int) c) & 0x0F;
726 result.Append ((char) hexBytes [idx]);
732 return result.ToString ();
735 static void UrlEncodeAndWrite (Stream stream, byte [] bytes)
740 int len = bytes.Length;
744 for (int i = 0; i < len; i++) {
745 char c = (char) bytes [i];
747 stream.WriteByte ((byte) '+');
748 else if ((c < '0' && c != '-' && c != '.') ||
749 (c < 'A' && c > '9') ||
750 (c > 'Z' && c < 'a' && c != '_') ||
752 stream.WriteByte ((byte) '%');
753 int idx = ((int) c) >> 4;
754 stream.WriteByte (hexBytes [idx]);
755 idx = ((int) c) & 0x0F;
756 stream.WriteByte (hexBytes [idx]);
758 stream.WriteByte ((byte) c);
764 List<RegisteredWaitHandle> wait_handles;
766 List<RegisteredWaitHandle> WaitHandles {
768 if (wait_handles == null)
769 wait_handles = new List<RegisteredWaitHandle> ();
774 [MonoTODO ("Is it enough to just unregister wait handles from ThreadPool?")]
775 public void CancelAsync ()
777 if (wait_handles == null)
779 lock (wait_handles) {
780 foreach (RegisteredWaitHandle handle in wait_handles)
781 handle.Unregister (null);
782 wait_handles.Clear ();
788 public void DownloadDataAsync (Uri uri)
790 DownloadDataAsync (uri, null);
793 public void DownloadDataAsync (Uri uri, object asyncState)
798 object [] cbArgs = new object [] {uri, asyncState};
799 WaitOrTimerCallback cb = delegate (object state, bool timedOut) {
800 object [] args = (object []) state;
801 byte [] data = timedOut ? null : DownloadData ((Uri) args [0]);
802 OnDownloadDataCompleted (
803 new DownloadDataCompletedEventArgs (data, null, timedOut, args [1]));
805 AutoResetEvent ev = new AutoResetEvent (true);
806 WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
812 public void DownloadFileAsync (Uri uri, string method)
814 DownloadFileAsync (uri, method, null);
817 public void DownloadFileAsync (Uri uri, string method, object asyncState)
822 object [] cbArgs = new object [] {uri, method, asyncState};
823 WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
824 object [] args = (object []) innerState;
826 DownloadFile ((Uri) args [0], (string) args [1]);
827 OnDownloadFileCompleted (
828 new AsyncCompletedEventArgs (null, timedOut, args [2]));
830 AutoResetEvent ev = new AutoResetEvent (true);
831 WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
835 // DownloadStringAsync
837 public void DownloadStringAsync (Uri uri)
839 DownloadStringAsync (uri, null);
842 public void DownloadStringAsync (Uri uri, object asyncState)
847 object [] cbArgs = new object [] {uri, asyncState};
848 WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
849 object [] args = (object []) innerState;
850 string data = timedOut ? null : DownloadString ((Uri) args [0]);
851 OnDownloadStringCompleted (
852 new DownloadStringCompletedEventArgs (data, null, timedOut, args [1]));
854 AutoResetEvent ev = new AutoResetEvent (true);
855 WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
861 public void OpenReadAsync (Uri uri)
863 OpenReadAsync (uri, null);
866 public void OpenReadAsync (Uri uri, object asyncState)
871 object [] cbArgs = new object [] {uri, asyncState};
872 WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
873 object [] args = (object []) innerState;
874 Stream stream = timedOut ? null : OpenRead ((Uri) args [0]);
875 OnOpenReadCompleted (
876 new OpenReadCompletedEventArgs (stream, null, timedOut, args [1]));
878 AutoResetEvent ev = new AutoResetEvent (true);
879 WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
885 public void OpenWriteAsync (Uri uri)
887 OpenWriteAsync (uri, null);
890 public void OpenWriteAsync (Uri uri, string method)
892 OpenWriteAsync (uri, method, null);
895 public void OpenWriteAsync (Uri uri, string method, object asyncState)
900 object [] cbArgs = new object [] {uri, method, asyncState};
901 WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
902 object [] args = (object []) innerState;
903 Stream stream = timedOut ? null : OpenWrite ((Uri) args [0], (string) args [1]);
904 OnOpenWriteCompleted (
905 new OpenWriteCompletedEventArgs (stream, null, timedOut, args [2]));
907 AutoResetEvent ev = new AutoResetEvent (true);
908 WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
914 public void UploadDataAsync (Uri uri, byte [] data)
916 UploadDataAsync (uri, null, data);
919 public void UploadDataAsync (Uri uri, string method, byte [] data)
921 UploadDataAsync (uri, method, data, null);
924 public void UploadDataAsync (Uri uri, string method, byte [] data, object asyncState)
929 object [] cbArgs = new object [] {uri, method, data, asyncState};
930 WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
931 object [] args = (object []) innerState;
932 byte [] data2 = timedOut ? null : UploadData ((Uri) args [0], (string) args [1], (byte []) args [2]);
933 OnUploadDataCompleted (
934 new UploadDataCompletedEventArgs (data2, null, timedOut, args [3]));
936 AutoResetEvent ev = new AutoResetEvent (true);
937 WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
943 public void UploadFileAsync (Uri uri, string file)
945 UploadFileAsync (uri, null, file);
948 public void UploadFileAsync (Uri uri, string method, string file)
950 UploadFileAsync (uri, method, file, null);
953 public void UploadFileAsync (Uri uri, string method, string file, object asyncState)
958 object [] cbArgs = new object [] {uri, method, file, asyncState};
959 WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
960 object [] args = (object []) innerState;
961 byte [] data = timedOut ? null : UploadFile ((Uri) args [0], (string) args [1], (string) args [2]);
962 OnUploadFileCompleted (
963 new UploadFileCompletedEventArgs (data, null, timedOut, args [3]));
965 AutoResetEvent ev = new AutoResetEvent (true);
966 WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
972 public void UploadStringAsync (Uri uri, string data)
974 UploadStringAsync (uri, null, data);
977 public void UploadStringAsync (Uri uri, string method, string data)
979 UploadStringAsync (uri, method, data, null);
982 public void UploadStringAsync (Uri uri, string method, string data, object asyncState)
987 object [] cbArgs = new object [] {uri, method, data, asyncState};
988 WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
989 object [] args = (object []) innerState;
990 string data2 = timedOut ? null : UploadString ((Uri) args [0], (string) args [1], (string) args [2]);
991 OnUploadStringCompleted (
992 new UploadStringCompletedEventArgs (data2, null, timedOut, args [3]));
994 AutoResetEvent ev = new AutoResetEvent (true);
995 WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
1001 public void UploadValuesAsync (Uri uri, NameValueCollection values)
1003 UploadValuesAsync (uri, null, values);
1006 public void UploadValuesAsync (Uri uri, string method, NameValueCollection values)
1008 UploadValuesAsync (uri, method, values, null);
1011 public void UploadValuesAsync (Uri uri, string method, NameValueCollection values, object asyncState)
1016 object [] cbArgs = new object [] {uri, method, values, asyncState};
1017 WaitOrTimerCallback cb = delegate (object innerState, bool timedOut) {
1018 object [] args = (object []) innerState;
1019 byte [] data = timedOut ? null : UploadValues ((Uri) args [0], (string) args [1], (NameValueCollection) args [2]);
1020 OnUploadValuesCompleted (
1021 new UploadValuesCompletedEventArgs (data, null, timedOut, args [3]));
1023 AutoResetEvent ev = new AutoResetEvent (true);
1024 WaitHandles.Add (ThreadPool.RegisterWaitForSingleObject (ev, cb, cbArgs, -1, true));
1028 protected virtual void OnDownloadDataCompleted (
1029 DownloadDataCompletedEventArgs args)
1031 if (DownloadDataCompleted != null)
1032 DownloadDataCompleted (this, args);
1035 protected virtual void OnDownloadFileCompleted (
1036 AsyncCompletedEventArgs args)
1038 if (DownloadFileCompleted != null)
1039 DownloadFileCompleted (this, args);
1042 protected virtual void OnDownloadStringCompleted (
1043 DownloadStringCompletedEventArgs args)
1045 if (DownloadStringCompleted != null)
1046 DownloadStringCompleted (this, args);
1049 protected virtual void OnOpenReadCompleted (
1050 OpenReadCompletedEventArgs args)
1052 if (OpenReadCompleted != null)
1053 OpenReadCompleted (this, args);
1056 protected virtual void OnOpenWriteCompleted (
1057 OpenWriteCompletedEventArgs args)
1059 if (OpenWriteCompleted != null)
1060 OpenWriteCompleted (this, args);
1063 protected virtual void OnUploadDataCompleted (
1064 UploadDataCompletedEventArgs args)
1066 if (UploadDataCompleted != null)
1067 UploadDataCompleted (this, args);
1070 protected virtual void OnUploadFileCompleted (
1071 UploadFileCompletedEventArgs args)
1073 if (UploadFileCompleted != null)
1074 UploadFileCompleted (this, args);
1077 protected virtual void OnUploadStringCompleted (
1078 UploadStringCompletedEventArgs args)
1080 if (UploadStringCompleted != null)
1081 UploadStringCompleted (this, args);
1084 protected virtual void OnUploadValuesCompleted (
1085 UploadValuesCompletedEventArgs args)
1087 if (UploadValuesCompleted != null)
1088 UploadValuesCompleted (this, args);