WebClient实际上是一个在HttpWebRequest之上的库,它的主要优点就是使用起来比较简单,但是它有两个致命缺陷,一是程序的回调在UI线程执行,会导致程序性能下降。另外一个,他没有实现本地缓存的控制策略。

那么HttpWebRequest呢,虽然它仍然无法支持GET方法下的本地缓存策略控制,但是它的性能实在是要好的太多,而且由于HttpWebRequest是个比WebClient更低级的库,你可以更好的对传输进行控制,所以我强烈推荐大家用HttpWebRequest,至少在微软对WebClient进行了改善之前是这样。

应为HttpWebRequest的异步回调函数会在自己的线程中执行,所以随之而来会带来一个问题,就是跨线程调用问题,这个问题可以通过这个方式,调用:

System.Windows.Deployment.Current.Dispatcher.BeginInvoke方法来在主线程中执行代码,这样就可以解决这个问题,并且我们可以通过封装HttpWebRequest来得到一个与WebClient使用方法类似的新类,下面我就把在项目中实现的这个类的代码给大家看看

  1. publicclass DownloadStringCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs 

  2. public DownloadStringCompletedEventArgs(string result, bool cancelled, Exception error, object userState) 

  3. base(error, cancelled, userState) 

  4. Result = result; 

  5. publicstring Result 

  6. get

  7. privateset

  8. publicclass OpenReadCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs 

  9. public OpenReadCompletedEventArgs(Stream result,bool cancelled,Exception error,object userState) 

  10. base(error, cancelled, userState) 

  11. Result = result; 

  12. public Stream Result 

  13. get

  14. privateset

  15. publicdelegatevoid DownloadStringCompletedEventHandler(Object sender, DownloadStringCompletedEventArgs e); 

  16. publicdelegatevoid OpenReadCompletedEventHandler(object sender, OpenReadCompletedEventArgs e); 

  17. publicclass NoCacheWebClient 

  18. HttpWebRequest _webRequest = null

  19. privatestring _result = ""

  20. privatebyte[] _buffer; 

  21. constint BUFFER_SIZE = 1024; 

  22. MemoryStream _memStream = null

  23. object _userToken = null

  24. staticstring cache = Guid.NewGuid().ToString(); 

  25. public NoCacheWebClient() 

  26. _buffer = newbyte[BUFFER_SIZE]; 

  27. Encoding = Encoding.UTF8; 

  28. _memStream = new MemoryStream(); 

  29. publicevent DownloadStringCompletedEventHandler DownloadStringCompleted; 

  30. publicevent OpenReadCompletedEventHandler OpenReadCompleted; 

  31. publicvoid CancelAsync() 

  32. if (_webRequest != null

  33. _webRequest.Abort(); 

  34. _result = ""

  35. _userToken = null

  36. public Encoding Encoding 

  37. get

  38. set

  39. private Uri RequestUri 

  40. set

  41. get

  42. publicvoid OpenReadAsync(Uri address) 

  43. RequestUri = address; 

  44. _webRequest = (HttpWebRequest)HttpWebRequest.Create(address.AbsoluteUri); 

  45. _webRequest.BeginGetResponse(StreamRespCallback, null); 

  46. privatevoid StreamRespCallback(IAsyncResult asynchronousResult) 

  47. try

  48. HttpWebResponse response = (HttpWebResponse)_webRequest.EndGetResponse(asynchronousResult); 

  49. Stream responseStream = response.GetResponseStream(); 

  50. if (OpenReadCompleted != null

  51. System.Windows.Deployment.Current.Dispatcher.BeginInvoke(OpenReadCompleted, newobject[] { thisnew OpenReadCompletedEventArgs(responseStream, falsenull, _userToken) }); 

  52. catch (WebException e) 

  53. string message = e.Message; 

  54. publicvoid DownloadStringAsync(Uri address) 

  55. _result = ""

  56. _memStream = new MemoryStream(); 

  57. string cacheValue = ""

  58. if (address.Query.Length == 0) 

  59. cacheValue = "?Cache=" + cache; 

  60. else

  61. cacheValue = "&Cache=" + cache; 

  62. Uri newAddress = new Uri(address.AbsoluteUri + cacheValue, UriKind.RelativeOrAbsolute); 

  63. RequestUri = newAddress; 

  64. _webRequest = (HttpWebRequest)HttpWebRequest.Create(newAddress.AbsoluteUri); 

  65. _webRequest.BeginGetResponse(RespCallback, null); 

  66. publicvoid DownloadStringAsync(Uri address,object userToken) 

  67. _result = ""

  68. _userToken = userToken; 

  69. _memStream = new MemoryStream(); 

  70. string cacheValue = ""

  71. if (address.Query.Length == 0) 

  72. cacheValue = "?Cache=" + cache; 

  73. else

  74. cacheValue = "&Cache=" + cache; 

  75. Uri newAddress = new Uri(address.AbsoluteUri + cacheValue, UriKind.RelativeOrAbsolute); 

  76. RequestUri = newAddress; 

  77. _webRequest = (HttpWebRequest)HttpWebRequest.Create(newAddress.AbsoluteUri); 

  78. _webRequest.BeginGetResponse(RespCallback, userToken); 

  79. privatevoid RespCallback(IAsyncResult asynchronousResult) 

  80. try

  81. HttpWebResponse response = (HttpWebResponse)_webRequest.EndGetResponse(asynchronousResult); 

  82. Stream responseStream = response.GetResponseStream(); 

  83. responseStream.BeginRead(_buffer, 0, BUFFER_SIZE, new AsyncCallback(ReadCallback), responseStream); 

  84. catch (WebException e) 

  85. string message = e.Message; 

  86. privatevoid ReadCallback(IAsyncResult asyncResult) 

  87. try

  88. Stream stream = (Stream)asyncResult.AsyncState; 

  89. int read = stream.EndRead(asyncResult); 

  90. if (read > 0) 

  91. _memStream.Write(_buffer, 0, read); 

  92. stream.BeginRead(_buffer, 0, BUFFER_SIZE, new AsyncCallback(ReadCallback), stream); 

  93. else

  94. _result = Encoding.GetString(_memStream.ToArray(), 0, (int)_memStream.Length); 

  95. stream.Close(); 

  96. _memStream.Close(); 

  97. if (DownloadStringCompleted != null

  98. System.Windows.Deployment.Current.Dispatcher.BeginInvoke(DownloadStringCompleted, newobject[] { thisnew DownloadStringCompletedEventArgs(_result, falsenull, _userToken) }); 

  99. catch (System.Exception ex) 

  100. string message = ex.Message; 

  101. privatevoid WriteCallBack(IAsyncResult asyncResult) 

  102. try

  103. _memStream.EndWrite(asyncResult); 

  104. Stream stream = (Stream)asyncResult.AsyncState; 

  105. stream.BeginRead(_buffer, 0, BUFFER_SIZE, new AsyncCallback(ReadCallback), stream); 

  106. catch (System.Exception ex) 

  107. string message = ex.Message; 

 public class DownloadStringCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
    {
        public DownloadStringCompletedEventArgs(string result, bool cancelled, Exception error, object userState)
            : base(error, cancelled, userState)
        {
            Result = result;
        }
        public string Result
        {
            get;
            private set;
        }
    }
    public class OpenReadCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
    {
        public OpenReadCompletedEventArgs(Stream result,bool cancelled,Exception error,object userState)
            : base(error, cancelled, userState)
        {
            Result = result;
        }
        public Stream Result
        {
            get;
            private set;
        }

    }
    public delegate void DownloadStringCompletedEventHandler(Object sender, DownloadStringCompletedEventArgs e);
    public delegate void OpenReadCompletedEventHandler(object sender, OpenReadCompletedEventArgs e);
    public class NoCacheWebClient
    {
        HttpWebRequest _webRequest = null;
        private string _result = "";        
        private byte[] _buffer;
        const int BUFFER_SIZE = 1024;
        MemoryStream _memStream = null;
        object _userToken = null;
        static string cache = Guid.NewGuid().ToString();
        public NoCacheWebClient()
        {
            _buffer = new byte[BUFFER_SIZE];
            Encoding = Encoding.UTF8;
            _memStream = new MemoryStream();
        }

        
        public event DownloadStringCompletedEventHandler DownloadStringCompleted;
        public event OpenReadCompletedEventHandler OpenReadCompleted;

       
        public void CancelAsync()
        {
            if (_webRequest != null)
            {
                _webRequest.Abort();
                _result = "";
                _userToken = null;
            }
        }
        public Encoding Encoding
        {
            get;
            set;
        }
        private Uri RequestUri
        {
             set;
             get;
        }
        public void OpenReadAsync(Uri address)
        {
            RequestUri = address;
           
            _webRequest = (HttpWebRequest)HttpWebRequest.Create(address.AbsoluteUri);
            _webRequest.BeginGetResponse(StreamRespCallback, null);

        }

        private void StreamRespCallback(IAsyncResult asynchronousResult)
        {
            try
            {
                HttpWebResponse response = (HttpWebResponse)_webRequest.EndGetResponse(asynchronousResult);
                Stream responseStream = response.GetResponseStream();
                if (OpenReadCompleted != null)
                {                  
                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(OpenReadCompleted, new object[] { this, new OpenReadCompletedEventArgs(responseStream, false, null, _userToken) });
                }
            }
            catch (WebException e)
            {
                string message = e.Message;
            }
        }
        
        public void DownloadStringAsync(Uri address)
        {
            _result = "";
            _memStream = new MemoryStream();            
            string cacheValue = "";
            if (address.Query.Length == 0)
            {
                cacheValue = "?Cache=" + cache;
            }
            else
            {
                cacheValue = "&Cache=" + cache;
            }

            
            Uri newAddress = new Uri(address.AbsoluteUri + cacheValue, UriKind.RelativeOrAbsolute);            
            RequestUri = newAddress;
            _webRequest = (HttpWebRequest)HttpWebRequest.Create(newAddress.AbsoluteUri);
           
            _webRequest.BeginGetResponse(RespCallback, null);
        }
        public void DownloadStringAsync(Uri address,object userToken)
        {
            _result = "";
            _userToken = userToken;
            _memStream = new MemoryStream();
            string cacheValue = "";
            if (address.Query.Length == 0)
            {
                cacheValue = "?Cache=" + cache;
            }
            else
            {
                cacheValue = "&Cache=" + cache;
            }
            Uri newAddress = new Uri(address.AbsoluteUri + cacheValue, UriKind.RelativeOrAbsolute);
            RequestUri = newAddress;
            _webRequest = (HttpWebRequest)HttpWebRequest.Create(newAddress.AbsoluteUri);
            _webRequest.BeginGetResponse(RespCallback, userToken);
        }
        private void RespCallback(IAsyncResult asynchronousResult)
        {
            try
            {   
                HttpWebResponse response = (HttpWebResponse)_webRequest.EndGetResponse(asynchronousResult);                
                Stream responseStream = response.GetResponseStream();
                responseStream.BeginRead(_buffer, 0, BUFFER_SIZE, new AsyncCallback(ReadCallback), responseStream);
            }
            catch (WebException e)
            {
                string message = e.Message;
            }
        }
        private void ReadCallback(IAsyncResult asyncResult)
        {
            try
            {
                Stream stream = (Stream)asyncResult.AsyncState;
                int read = stream.EndRead(asyncResult);
                if (read > 0)
                {
                    _memStream.Write(_buffer, 0, read);
                    stream.BeginRead(_buffer, 0, BUFFER_SIZE, new AsyncCallback(ReadCallback), stream);
                }
                else
                {
                    _result = Encoding.GetString(_memStream.ToArray(), 0, (int)_memStream.Length);
                    stream.Close();
                    _memStream.Close();

                    if (DownloadStringCompleted != null)
                    {
                        System.Windows.Deployment.Current.Dispatcher.BeginInvoke(DownloadStringCompleted, new object[] { this, new DownloadStringCompletedEventArgs(_result, false, null, _userToken) });
                    }
                }
            }
            catch (System.Exception ex)
            {
                string message = ex.Message;
            }
        }

        private void WriteCallBack(IAsyncResult asyncResult)
        {
            try
            {
                _memStream.EndWrite(asyncResult);
                Stream stream = (Stream)asyncResult.AsyncState;
                stream.BeginRead(_buffer, 0, BUFFER_SIZE, new AsyncCallback(ReadCallback), stream);

            }
            catch (System.Exception ex)
            {
                string message = ex.Message;
            }
        }
        
    }

 

这个类的使用方法基本与WebClient类似,当然我只实现了部分函数和属性,而且这个程序会通过设置guid来强制刷新url避免缓存问题,这也实在是一个没有办法的办法,希望微软在下一个版本中能够改善这个问题。

 

 

http://blog.csdn.net/oldmanzhao/article/details/7294697