封装C#发送http请求成功后的callback

来源:互联网 发布:做浮雕的软件 编辑:程序博客网 时间:2024/05/22 01:41

目的其实很简单,是想要封装一个发送http的post请求的函数。

函数参数填url地址、请求参数、以及得到后台相应的回调函数、访问超时时间

形如:

public void HttpPost(string url, Dictionary<string, string> dic , Action<IAsyncResult> callback,int timeout)

网上找了之后发现HttpWebRequest 这个类可以实现这个功能

于是网上查到可以这么写

        /// <summary>        /// 异步post        /// </summary>        public void HttpPost(string url, Dictionary<string, string> dic , Action<string> callback)        {            Uri uri = new Uri(url);            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);            request.Method = "POST";            request.ContentType = "application/x-www-form-urlencoded";            HttpReqPack pack = new HttpReqPack(request, dic, callback);            request.BeginGetRequestStream(new AsyncCallback(RequestProceed),  pack);        }
这里的pack是自己封装的,目的是为了在BeginGetRequestStream这个函数第二个参数传入一些请求相关信息的数据,因为这个函数的第一个参数是一个委托,第二个参数是带入这个委托的参数其实主要的工作是在RequestProceed这个函数里完成的。以下是HttpReqPack类以及RequestProceed函数的定义。

HttpReqPack类:

        class HttpReqPack        {            public HttpWebRequest request;            public Dictionary<string, string> dic;            public Action<string> responesProceed;            public HttpReqPack(HttpWebRequest request, Dictionary<string, string> dic, Action<string> responseProceed)            {                this.request = request;                this.dic = dic;                this.responesProceed = responseProceed;            }        }


RequestProceed函数:

private void RequestProceed(IAsyncResult asyncResult)        {            HttpReqPack pack = (HttpReqPack)asyncResult.AsyncState;            Dictionary<string, string> dic = pack.dic;            HttpWebRequest request = pack.request;//(HttpWebRequest)asyncResult.AsyncState;            StreamWriter postDataWriter = new StreamWriter(request.EndGetRequestStream(asyncResult));            int i = 0;            foreach (var item in dic)            {                if(i==0)                    postDataWriter.Write(item.Key+"="+item.Value);                else                    postDataWriter.Write("&"+item.Key + "=" + item.Value);                i++;            }            postDataWriter.Close();            request.BeginGetResponse(t=> {                String responseString;                try                {                    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(t);                    StreamReader responseReader = new StreamReader(response.GetResponseStream());                    responseString = responseReader.ReadToEnd();                }                catch(Exception e)                {                    responseString = JsonConvert.SerializeObject(new ReturnMsg(PublicVar.SVR_UNKNOW_ERROR, e.Message));                }                //调用一下委托                pack.responesProceed.Invoke(responseString);            },  request);        }
在这函数中,就用到了刚才封装的那个HttpReqPack类,把发送参数、url地址还有最重要的是刚才构造的HttpWebRequest对象取出来使用。这个HttpWebRequest对象把他保存在一个名为request的对象,他有个BeginGetResponse方法,这个方法才是发起网络请求的核心方法(经过后期打印日志发现,最耗时的方法也是这个),第一个参数仍然是一个带一个参数无返回值的委托,为了简洁代码,我使用了一个lambda表达式来写,BeginGetResponse的第二个参数是request对象本身就不多说了。

这个委托带的一个参数是HttpWebRequest类型的request对象本身,委托的方法体内使用了另一个重要的方法EndGetResponse,这个方法作用是等待刚才发起的网络请求的结束,当然也可能抛异常,比如网络地址不存在等等,所以用了try..catch..去捕获。EndGetResponse函数的返回值是HttpWebResponse 类型的,把结果保存在response变量,就可以得到最终的后台返回的数据。
最后,调用事先保存在pack中的responesProceed方法,去回调到外层最初调用HttpPost函数的地方。
调用地方的代码可以这样:

 new HttpClient().HttpPost(url, dic, t=> {    String responseString = t;    MessageBox.Show(responseString); });



到目前为止,差不多已经完成了,可是还差一个超时时间设置,我希望自己设置http请求的超时时间,这个如何解决?

尝试了设置request的            

request.Timeout = timeout;

        request.ReadWriteTimeout = 1;

这两个属性都不管用。


查看了msdn里HttpWebRequest.BeginGetResponse函数,参考里面的例子代码。完成了异步类型超时的设置方式,以下是完整的代码:


using Charge.Public;using Charge.Record;using Newtonsoft.Json;using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Net;using System.Net.Http;using System.Text;using System.Threading;namespace Charge{    class HttpSender    {                class HttpReqPack        {            public RequestState requestState;            public Dictionary<string, string> dic;            public Action<string> responesProceed;            public int timeout;            public HttpReqPack(RequestState requestState, Dictionary<string, string> dic, Action<string> responseProceed,int timeout)            {                this.requestState = requestState;                this.dic = dic;                this.responesProceed = responseProceed;                this.timeout = timeout;            }        }        /// <summary>        /// 异步post        /// </summary>        public void HttpPost(string url, Dictionary<string, string> dic , int timeout, Action<string> callback)        {            Uri uri = new Uri(url);            RequestState myRequestState = new RequestState();                      HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);            myRequestState.request = request;            request.Method = "POST";                        request.ContentType = "application/x-www-form-urlencoded";            HttpReqPack pack = new HttpReqPack(myRequestState, dic, callback, timeout);            request.BeginGetRequestStream(new AsyncCallback(RequestProceed),  pack);        }        // Abort the request if the timer fires.         private static void TimeoutCallback(object state, bool timedOut)        {            if (timedOut)            {                HttpWebRequest request = state as HttpWebRequest;                if (request != null)                {                    request.Abort();                }            }        }        public static ManualResetEvent allDone = new ManualResetEvent(false);        private void RequestProceed(IAsyncResult asyncResult)        {            HttpReqPack pack = (HttpReqPack)asyncResult.AsyncState;            Dictionary<string, string> dic = pack.dic;            HttpWebRequest request = pack.requestState.request;            StreamWriter postDataWriter = new StreamWriter(request.EndGetRequestStream(asyncResult));            int i = 0;            foreach (var item in dic)            {                if(i==0)                    postDataWriter.Write(item.Key+"="+item.Value);                else                    postDataWriter.Write("&"+item.Key + "=" + item.Value);                i++;            }            postDataWriter.Close();            LogHelper.WriteDebug("http计时程序", " request.BeginGetResponse");            try            {                IAsyncResult result = request.BeginGetResponse(t=> {                    String responseString;                    try                    {                        LogHelper.WriteDebug("http计时程序", " request.EndGetResponse");                        HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(t);                        LogHelper.WriteDebug("http计时程序", " response.GetResponseStream()");                        StreamReader responseReader = new StreamReader(response.GetResponseStream());                        LogHelper.WriteDebug("http计时程序", "responseReader.ReadToEnd()");                        responseString = responseReader.ReadToEnd();                        LogHelper.WriteDebug("http计时程序", " 完成");                    }                    catch(Exception e)                    {                        responseString = JsonConvert.SerializeObject(new ReturnMsg(PublicVar.SVR_UNKNOW_ERROR, e.Message));                    }                    //调用一下委托                    pack.responesProceed.Invoke(responseString);                },  request);                // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted                 ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request, pack.timeout, true);                // The response came in the allowed time. The work processing will happen in the                  // callback function.                 allDone.WaitOne();                // Release the HttpWebResponse resource.                 pack.requestState.response.Close();            }            catch (Exception e)            {                LogHelper.WriteDebug("报错", e.Message);            }        }    }}










0 0