Windows Phone 7 的Http网络库使用技巧

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

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

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

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

 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避免缓存问题,这也实在是一个没有办法的办法,希望微软在下一个版本中能够改善这个问题。


WinHTTP提供以下功能: WinHttpAddRequestHeaders 向HTTP请求句柄添加一个或多个HTTP请求标头。 WinHttpCheckPlatform 确定WinHTTP是否支持当前平台。 WinHttpCloseHandle 关闭单个 HINTERNET句柄。 WinHttpConnect 指定HTTP请求的初始目标服务器。 WinHttpCrackUrl 将URL分为其组成部分,例如主机名和路径。 WinHttpCreateProxyResolver 创建WinHttpGetProxyForUrlEx使用的句柄。 WinHttpCreateUrl 从组件部分创建URL,例如主机名和路径。 WinHttpDetectAutoProxyConfigUrl 查找代理自动配置(PAC)文件的URL。此功能报告PAC文件的URL,但不下载该文件。 WinHttpFreeProxyResult 释放从以前的调用WinHttpGetProxyResult检索的数据。 WinHttpGetDefaultProxyConfiguration 从注册表中检索默认的WinHTTP代理配置。 WinHTTPGetIEProxyConfigForCurrentUser 获取当前用户的Internet Explorer(IE)代理配置。 WinHttpGetProxyForUrl 检索指定URL的代理信息。 WinHttpGetProxyForUrlEx 检索指定URL的代理信息。 WinHttpGetProxyResult 检索到调用的结果WinHttpGetProxyForUrlEx。 WinHttpOpen 初始化应用程序对WinHTTP功能的使用。 WinHttpOpenRequest 创建HTTP请求句柄。 WinHttpQueryAuthSchemes 返回服务器支持的授权方案。 WinHttpQueryDataAvailable 返回可立即与读取数据的字节数 WinHttpReadData。 WinHttpQueryHeaders 检索与HTTP请求相关联的头信息。 WinHttpQueryOption 在指定的句柄上查询Internet选项。 WinHttpReadData 从WinHttpOpenRequest函数打开的句柄中读取数据 。 WinHttpReceiveResponse 结束由WinHttpSendRequest启动的HTTP请求 。 WinHttpResetAutoProxy 重置自动代理。 WinHttpSendRequest 将指定的请求发送到HTTP服务器。 WinHttpSetCredentials 将所需的授权凭证传递给服务器。 WinHttpSetDefaultProxyConfiguration 在注册表中设置默认的WinHTTP代理配置。 WinHttpSetOption 设置Internet选项。 WinHttpSetStatusCallback 设置WinHTTP可以在操作过程中进行调用的回调函数。 WinHttpSetTimeouts 设置涉及HTTP事务的各种超时。 WinHttpTimeFromSystemTime 根据HTTP版本1.0规范格式化日期和时间。 WinHttpTimeToSystemTime 获取HTTP时间/日期字符串并将其转换为 SYSTEMTIME结构。 WinHttpWriteData 将请求数据写入HTTP服务器。 WinHttpWebSocketClose 关闭WebSocket连接。 WinHttpWebSocketCompleteUpgrade 完成由WinHttpSendRequest启动的WebSocket握手。 WinHttpWebSocketQueryCloseStatus 获取服务器发送的关闭状态。 WinHttpWebSocketReceive 从WebSocket连接接收数据。 WinHttpWebSocketSend 通过WebSocket连接发送数据。 WinHttpWebSocketShutdown 向WebSocket连接发送关闭框架
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值