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

本文介绍了一个自定义的HTTP POST请求封装方法,通过异步处理实现了请求的发送与响应的接收,并详细解释了如何设置请求超时。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目的其实很简单,是想要封装一个发送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);
            }
        }



    }
}










评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值