源于
提示:该程序为C#的Winform程序,可在Windows上直接运行.
之前写了一个Winform程序,需要异步更新UI(例如,在Android中,是明确禁止同步更新UI的.).于是请教了一些网友,得出下面的程序.
其实原理都比较简单,就是把网络请求放到另外一个线程里面去执行.等网络请求线程执行完成之后,通过回调或其他方式执行UI线程更新.
运行截图
程序运行截图如下,图示为已经加载完成数据的效果:
源码
完整源码在: Gitee仓库
请求的网络地址为: http://www.weather.com.cn/data/sk/101270101.html,有时候网络会比较慢..
发送请求封装部分:
// allDone 属性包含 ManualResetEvent 类的实例,它指示请求完成。 public ManualResetEvent allDone = new ManualResetEvent(false); // 它创建 WebRequest wreq 和 RequestState rs,调用 BeginGetResponse 开始处理请求,然后调用 allDone.WaitOne() 方法, // 以便应用程序不会在回调完成前退出。 在从 Internet 资源读取响应后,Main() 将该响应写入到控制台,应用程序结束。 public void SendGet(string url, HttpResultGet resultGet, FormInterface formTransInterface, WebHeaderCollection whcl = null) { try { WebRequest wreq = WebRequest.Create(url); if (whcl != null) { ((HttpWebRequest)wreq).Headers = whcl; } // Create the state object. ASyncRequestState rs = new ASyncRequestState { // Put the request into the state object so it can be passed around. Request = wreq }; // Issue the async request. IAsyncResult r = wreq.BeginGetResponse( new AsyncCallback(RespCallback), rs); // Wait until the ManualResetEvent is set so that the application // does not exit until after the callback is called. allDone.WaitOne(); if (rs.RequestData.ToString().Length > 0) { resultGet.ResultSet(rs.RequestData.ToString(), formTransInterface); } } catch (WebException) { resultGet.ResultSet("[请求错误]网络请求发生未知错误,请稍候重试!", formTransInterface); } catch (Exception) { resultGet.ResultSet("[请求错误]网络请求发生未知错误,请稍候重试!", formTransInterface); } }
异步回调封装部分:
// RespCallBack() 方法实现 Internet 请求的异步回调方法。 // 该方法创建包含来自 Internet 资源的响应的 WebResponse 实例, // 获取响应流,然后开始从该流异步读取数据。 private void RespCallback(IAsyncResult ar) { // Get the ASyncRequestState object from the async result. ASyncRequestState rs = (ASyncRequestState)ar.AsyncState; // Get the WebRequest from AsyncRequestState. WebRequest req = rs.Request; // Call EndGetResponse, which produces the WebResponse object // that came from the request issued above. WebResponse resp = req.EndGetResponse(ar); // Start reading data from the response stream. Stream ResponseStream = resp.GetResponseStream(); // Store the response stream in AsyncRequestState to read // the stream asynchronously. rs.ResponseStream = ResponseStream; // Open the stream using a StreamReader for easy access. StreamReader reader = new StreamReader(ResponseStream); // Read the content. string responseFromServer = reader.ReadToEnd(); rs.RequestData.Append( responseFromServer); // Close down the response stream. reader.Close(); // Set the ManualResetEvent so the main thread can exit. allDone.Set(); }
代码调用:
/** * 发送异步网络请求. * * */ public void SendGet(string url, FormInterface formInterface) { // 随便显示的一个天气地址. AsyncHttpUtil asyncHttpUtil = new AsyncHttpUtil(); asyncHttpUtil.SendGet(url, new SendHTTP(), formInterface); } // 异步回调 void HttpResultGet.ResultSet(string result, FormInterface formInterface) { formInterface.SendResult(result); }
程序入口调用:
/** * 接收异步返回结果. * */ void FormInterface.SendResult(string text) { MessageBox.Show(text); this.targetText.Text = text; } /** * 模拟发送异步请求. * */ private void send_Click(object sender, EventArgs e) { SendHTTP send = new SendHTTP(); send.SendGet("http://www.weather.com.cn/data/sk/101270101.html", this); }
完整源码在: Gitee仓库