异步WebRequest用法
public class Rqt_Request { public Rqt_Request() { this.URI = string.Empty; this.Cache = HttpRequestCacheLevel.CacheIfAvailable; this.Timeout = 0xea60; this.Query = string.Empty; CookieContainer container = new CookieContainer(); this.Cookies = container; this.Token = new CancellationToken(); } public Rqt_Request(string uri, HttpRequestCacheLevel cache, int timeout, string query, CancellationToken token, object state, CookieContainer cookies) { this.URI = string.Empty; this.Cache = HttpRequestCacheLevel.CacheIfAvailable; this.Timeout = 0xea60; this.Query = string.Empty; CookieContainer container = new CookieContainer(); this.Cookies = container; this.Token = new CancellationToken(); this.URI = uri; this.Cache = cache; this.Timeout = timeout; this.Token = token; this.State = RuntimeHelpers.GetObjectValue(state); this.Query = query; if (cookies != null) { this.Cookies = cookies; } } public HttpRequestCacheLevel Cache { get; set; } public CookieContainer Cookies { get; set; } public string Query { get; set; } public object State { get; set; } public int Timeout { get; set; } public CancellationToken Token { get; set; } public string URI { get; set; } }
public class Rqt_State : IDisposable { private int _bufferSize; private string _host; private string _Uri; private object _writeLock; private MemoryStream _WriteStream; private bool disposedValue; public Rqt_State() { this._host = string.Empty; this._bufferSize = 0; this._writeLock = new object(); this._Uri = ""; this._WriteStream = new MemoryStream(); this.Status = RequestStatus.NotStarted; } ~Rqt_State() { Dispose(true); } public Rqt_State(Rqt_Async owner, int buffersize) : this() { this._bufferSize = buffersize; this.BufferBytes = new byte[this._bufferSize + 1]; this.Owner = owner; } public void AppendStream(int numbytes) { this.WriteStream.Write(this.BufferBytes, 0, numbytes); } public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!this.disposedValue) { if (disposing) { if (this.WriteStream != null) { this.WriteStream.Dispose(); } if (this.BufferStream != null) { this.BufferStream.Dispose(); } } this._WriteStream = null; this.BufferStream = null; this.Request = null; this.Response = null; this.BufferBytes = null; } this.disposedValue = true; } internal byte[] BufferBytes { get; set; } internal Stream BufferStream { get; set; } public System.Exception Exception { get; set; } public string Host { get { return this._host; } } public bool IsTimedOut { get; set; } public Rqt_Async Owner { get; set; } public HttpWebRequest Request { get; set; } public HttpWebResponse Response { get; set; } public Image ResponseImage { get { try { return Image.FromStream(this.ResponseStream); } catch (System.Exception exception1) { ProjectData.SetProjectError(exception1); System.Exception exception = exception1; } return null; } } public MemoryStream ResponseStream { get { MemoryStream stream = new MemoryStream(); this.WriteStream.WriteTo(stream); stream.Position = 0L; return stream; } } public string ResponseText { get { string str = string.Empty; try { StreamReader reader = new StreamReader(this.ResponseStream, true); str = reader.ReadToEnd(); reader.Close(); } catch (System.Exception exception1) { ProjectData.SetProjectError(exception1); System.Exception exception = exception1; } return str; } } public object State { get; set; } public RequestStatus Status { get; set; } public CancellationToken Token { get; set; } public string Uri { get { return this._Uri; } set { this._Uri = value; try { this._host = new System.Uri(this._Uri).Host; } catch (System.Exception exception1) { ProjectData.SetProjectError(exception1); System.Exception exception = exception1; } } } public MemoryStream WriteStream { get { object expression = this._writeLock; ObjectFlowControl.CheckForSyncLockOnValueType(expression); lock (expression) { return this._WriteStream; } } } }
/// <summary> /// 异步请求 /// </summary> public class Rqt_Async { #region 变量 private static List<string> _Cached = new List<string>(); private ManualResetEvent allDone; private int BUFFER_SIZE; #endregion #region 静态事件 public delegate void OnPhaseChangeEventHandler(Rqt_Async sender, RequestPhase e); private static OnPhaseChangeEventHandler OnPhaseChangeEvent; public static event OnPhaseChangeEventHandler OnPhaseChange { add { Rqt_Async.OnPhaseChangeEvent += value; } remove { Rqt_Async.OnPhaseChangeEvent -= value; } } #endregion #region 事件 public delegate void OnCancelEventHandler(Rqt_Async sender); private OnCancelEventHandler OnCancelEvent; public event OnCancelEventHandler OnCancel { add { this.OnCancelEvent += value; } remove { this.OnCancelEvent -= value; } } protected delegate void OnChangedEventHandler(Rqt_Async sender, RequestEventType status); private OnChangedEventHandler OnChangedEvent; protected event OnChangedEventHandler OnChanged { add { this.OnChangedEvent += value; } remove { this.OnChangedEvent -= value; } } public delegate void OnErrorEventHandler(Rqt_Async sender); private OnErrorEventHandler OnErrorEvent; public event OnErrorEventHandler OnError { add { this.OnErrorEvent += value; } remove { this.OnErrorEvent -= value; } } public delegate void OnFinishedEventHandler(Rqt_Async sender); private OnFinishedEventHandler OnFinishedEvent; public event OnFinishedEventHandler OnFinished { add { this.OnFinishedEvent += value; } remove { this.OnFinishedEvent -= value; } } public delegate void OnSuccessEventHandler(Rqt_Async sender); private OnSuccessEventHandler OnSuccessEvent; public event OnSuccessEventHandler OnSuccess { add { this.OnSuccessEvent += value; } remove { this.OnSuccessEvent -= value; } } public delegate void OnUpdateEventHandler(Rqt_Async sender); private OnUpdateEventHandler OnUpdateEvent; public event OnUpdateEventHandler OnUpdate { add { this.OnUpdateEvent += value; } remove { this.OnUpdateEvent -= value; } } #endregion #region 构造函数 public Rqt_Async() { this.OnChanged += (s, e) => Changed(s, e); this.Finished = new ManualResetEvent(false); this.allDone = new ManualResetEvent(false); this.BUFFER_SIZE = 0x80000; this.EnableRaisingEvents = true; } public Rqt_Async(object owner) : this() { this.Owner = owner; } #endregion #region 属性 public static List<string> Cached { [MethodImpl(MethodImplOptions.Synchronized)] get { return _Cached; } } public Rqt_State CurrentRequest { get; set; } public bool EnableRaisingEvents { get; set; } public ManualResetEvent Finished { get; set; } public object Owner { get; set; } #endregion protected void Changed(Rqt_Async sender, RequestEventType event_type) { if (this.EnableRaisingEvents) { switch (((int)event_type)) { case 0: { if (OnErrorEvent != null) { OnErrorEvent(sender); } break; } case 1: { if (OnSuccessEvent != null) { OnSuccessEvent(sender); } break; } case 2: { if (OnCancelEvent != null) { OnCancelEvent(sender); } break; } case 3: { if (OnUpdateEvent != null) { OnUpdateEvent(sender); } break; } case 4: { if (OnFinishedEvent != null) { OnFinishedEvent(sender); } break; } } } } /// <summary> /// 从缓存获取请求数据 /// </summary> /// <param name="state"></param> /// <returns></returns> private bool GetFromCache(Rqt_State state) { bool flag=false; WebRequest wr = WebRequest.Create(state.Uri); wr.Timeout = 0x1388; wr.CachePolicy = new RequestCachePolicy(RequestCacheLevel.CacheOnly); try { WebResponse response = wr.GetResponse(); if (response.IsFromCache) { state.Response = (HttpWebResponse)response; state.Request = (HttpWebRequest)wr; response.GetResponseStream().CopyTo(state.WriteStream); flag = true; } } catch (Exception ex) { flag = false; Console.WriteLine(ex.Message); } return flag; } /// <summary> /// 异步读取回调函数 /// </summary> /// <param name="asyncResult"></param> internal void ReadCallBack(IAsyncResult asyncResult) { Rqt_State state = (Rqt_State)asyncResult.AsyncState; try { state.Token.ThrowIfCancellationRequested(); if (OnPhaseChangeEvent != null) { OnPhaseChangeEvent(this, RequestPhase.Read); } Stream bufferStream = state.BufferStream; int numbytes = bufferStream.EndRead(asyncResult); if (numbytes > 0) { state.AppendStream(numbytes); if (OnChangedEvent != null) { OnChangedEvent(this, RequestEventType.Update); } IAsyncResult result = bufferStream.BeginRead(state.BufferBytes, 0, this.BUFFER_SIZE, new AsyncCallback(this.ReadCallBack), state); return; } state.Status = RequestStatus.Succeded; bufferStream.Close(); } catch (Exception ex) { SetRequestStateError(state, ref ex); } this.allDone.Set(); } /// <summary> /// 释放状态 /// </summary> public void ReleaseState() { if (this.CurrentRequest != null) { this.CurrentRequest.Dispose(); } this.CurrentRequest = null; } /// <summary> /// 异步请求完成时的回调函数 /// </summary> /// <param name="asynchronousResult"></param> internal void RespCallback(IAsyncResult asynchronousResult) { Rqt_State asyncState = (Rqt_State)asynchronousResult.AsyncState; try { asyncState.Token.ThrowIfCancellationRequested(); HttpWebRequest request = asyncState.Request; asyncState.Response = (HttpWebResponse)request.EndGetResponse(asynchronousResult); Stream responseStream = asyncState.Response.GetResponseStream(); asyncState.BufferStream = responseStream; IAsyncResult result = responseStream.BeginRead(asyncState.BufferBytes, 0, this.BUFFER_SIZE, new AsyncCallback(this.ReadCallBack), asyncState); return; } catch (Exception ex) { SetRequestStateError(asyncState, ref ex); } this.allDone.Set(); } private static void SetRequestStateError(Rqt_State requestState, ref Exception ex) { RequestStatus status = RequestStatus.Exception; if (requestState.Token.IsCancellationRequested) { ex = null; requestState.Request.Abort(); status = RequestStatus.Canceled; } else if (requestState.IsTimedOut) { ex = new TimeoutException(); status = RequestStatus.Exception; } requestState.Status = status; requestState.Exception = ex; } /// <summary> /// 开始异步访问 /// </summary> /// <param name="r"></param> internal virtual void Start(Rqt_Request r) { this.Start(r.URI, r.State, r.Token, (RequestCacheLevel)r.Cache, r.Cookies, r.Query, r.Timeout); } /// <summary> /// 开始异步访问 /// </summary> /// <param name="uri"></param> /// <param name="state"></param> /// <param name="ct"></param> /// <param name="cache"></param> /// <param name="cookies"></param> /// <param name="PostQuery"></param> /// <param name="Timeout"></param> internal virtual void Start(string uri, object state, CancellationToken ct, RequestCacheLevel cache, CookieContainer cookies, string PostQuery, int Timeout) { this.allDone = new ManualResetEvent(false); this.Finished = new ManualResetEvent(false); this.CurrentRequest = new Rqt_State(this, this.BUFFER_SIZE); try { this.CurrentRequest.Token = ct; this.CurrentRequest.Uri = uri; this.CurrentRequest.State = state; #region 从缓存读取数据 if (((cache == RequestCacheLevel.Default) | (cache == RequestCacheLevel.CacheIfAvailable)) | (cache == RequestCacheLevel.CacheOnly)) { if (Cached.Contains(this.CurrentRequest.Uri) && this.GetFromCache(this.CurrentRequest)) { if (ct.IsCancellationRequested) { this.CurrentRequest.Status = RequestStatus.Canceled; } else { this.CurrentRequest.Status = RequestStatus.Succeded; } this.allDone.Set(); } cache = RequestCacheLevel.Reload; } HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.CurrentRequest.Uri); Network.RequestInitialize(request); request.CookieContainer = cookies; request.CachePolicy = new RequestCachePolicy(cache); if (!string.IsNullOrEmpty(PostQuery)) { byte[] bytes = Encoding.UTF8.GetBytes(PostQuery); if (bytes.Length > 0) { request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = bytes.Length; request.GetRequestStream().Write(bytes, 0, bytes.Length); } } this.CurrentRequest.Request = request; this.CurrentRequest.Status = RequestStatus.Running; if (OnPhaseChangeEvent != null) { OnPhaseChangeEvent(this, RequestPhase.Begin); } WaitHandle wh=request.BeginGetResponse(new AsyncCallback(this.RespCallback), this.CurrentRequest).AsyncWaitHandle; RegisteredWaitHandle handle = ThreadPool.RegisterWaitForSingleObject(wh, new WaitOrTimerCallback(Rqt_Async.TimeoutCallback), this.CurrentRequest, Timeout, true); if (OnPhaseChangeEvent != null) { OnPhaseChangeEvent(this, RequestPhase.Wait); } this.allDone.WaitOne(); if (OnPhaseChangeEvent != null) { OnPhaseChangeEvent(this, RequestPhase.End); } #endregion } catch (Exception ex) { this.CurrentRequest.Status = RequestStatus.Exception; this.CurrentRequest.Exception = ex; } finally { if (this.CurrentRequest.Response != null) { this.CurrentRequest.Response.Close(); } } switch (this.CurrentRequest.Status) { case RequestStatus.Succeded: if (!Cached.Contains(this.CurrentRequest.Uri)) { Cached.Add(this.CurrentRequest.Uri); } if (OnChangedEvent != null) { OnChangedEvent(this, RequestEventType.Success); } break; case RequestStatus.Canceled: Cached.Remove(this.CurrentRequest.Uri); if (OnChangedEvent != null) { OnChangedEvent(this, RequestEventType.Canceled); } break; case RequestStatus.Exception: Cached.Remove(this.CurrentRequest.Uri); if (OnChangedEvent != null) { OnChangedEvent(this, RequestEventType.Exception); } break; } this.Finished.Set(); if (OnChangedEvent != null) { OnChangedEvent(this, RequestEventType.Finished); } } /// <summary> /// 异步请求超时回调函数 /// </summary> /// <param name="state"></param> /// <param name="timedOut"></param> internal static void TimeoutCallback(object state, bool timedOut) { if (timedOut) { Rqt_State state2 = (Rqt_State)state; if ((state2 != null) && (state2.Request != null)) { state2.IsTimedOut = true; state2.Request.Abort(); } } } }