前言:
由於js 遠程請求 XMLHttpRequest() 不支持多線程,所以用C# 寫了個dll 多線程遠程抓住供js調用。
最初代碼為:
C#代碼
/// <summary> /// 異步請求入口 /// </summary> /// <param name="url">傳入http地址 注意加http</param> /// <param name="timeoutStr">超時時間</param> public void AsyncGet(string url, int timeoutStr) { try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(url)); request.Timeout = timeoutStr; request.BeginGetResponse(new AsyncCallback(ReadCallBack), request); } catch (Exception) { } } /// <summary> /// 執行回調時候異步最終拿到值 /// 正常獲取反饋值,異常時候值為 timeout /// </summary> public string returnContent { get; set; } /// <summary> /// 執行異步回調請求 /// </summary> /// <param name="asynchronousResult"></param> private void ReadCallBack(IAsyncResult asynchronousResult) { try { HttpWebRequest reqeust = (HttpWebRequest)asynchronousResult.AsyncState; HttpWebResponse response = (HttpWebResponse)reqeust.EndGetResponse(asynchronousResult); StreamReader readContent = new StreamReader(response.GetResponseStream()); returnContent = readContent.ReadToEnd().ToString(); } catch (Exception) { returnContent = "timeout"; } }
js 代碼:
var Gtime = 5; function getUrl (turl) { if (Gtime==5) { comActiveX.AsyncGet(turl,Gtime); } if (Gtime>0 && comActiveX.returnContent==undefined) { setTimeout("getUrl('"+turl+"')",1000); alert(comActiveX.returnContent); Gtime -- ; }else{ document.write( comActiveX.returnContent); } }
這里存在問題,js必須一直去詢問dll 是否獲取到數據,直到獲取到數據才做下面處理,雖然其中可以做其他事情,但是這跟同步等待沒有多大區別。
windows 經典編程 有句話叫“don't call me , I will call you!” ,這就是事件的引入,那么這里可以不可以優化為,當有數據拿到以后自動通知js,js能不能注冊一個回調函數。 開始一通嘗試,最終找到相關答案:
C# 加入以下代碼:
public delegate void EventHandler(string data); [Guid("9771B223-6188-4849-B292-C7D9D8173E49")] [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] public interface ControlEvents { [DispId(0x60020000)] void eventsGet(string data); } /// <summary> /// 采集類 /// </summary> [ClassInterface(ClassInterfaceType.AutoDual), ComSourceInterfaces(typeof(ControlEvents))] public class CollectGood : UserControl { public event EventHandler eventsGet; private delegate void UpEventDelegate(string msg); public void Reback(string msg) { UpEventDelegate up = new UpEventDelegate(UpEvent); this.BeginInvoke(up, msg); } private void UpEvent(string msg) { if (eventsGet != null) { eventsGet(msg); } } #region httpWebRequest 異步請求Get方法 /// <summary> /// 異步請求入口 /// </summary> /// <param name="url">傳入http地址 注意加http</param> /// <param name="timeoutStr">超時時間</param> public void AsyncGet(string url, int timeoutStr) { try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(url)); request.Timeout = timeoutStr; request.BeginGetResponse(new AsyncCallback(ReadCallBack), request); } catch (Exception) { } } /// <summary> /// 執行回調時候異步最終拿到值 /// 正常獲取反饋值,異常時候值為 timeout /// </summary> public string returnContent { get; set; } /// <summary> /// 執行異步回調請求 /// </summary> /// <param name="asynchronousResult"></param> private void ReadCallBack(IAsyncResult asynchronousResult) { try { HttpWebRequest reqeust = (HttpWebRequest)asynchronousResult.AsyncState; HttpWebResponse response = (HttpWebResponse)reqeust.EndGetResponse(asynchronousResult); StreamReader readContent = new StreamReader(response.GetResponseStream()); returnContent = readContent.ReadToEnd().ToString(); Reback(returnContent); } catch (Exception) { returnContent = "timeout"; } } #endregion
js部分:
<OBJECT id="comActiveX" width="" height="" classid="CLSID:7b8bfbe3-7f62-47e0-919c-6aa2315e6db9"> </OBJECT> <SCRIPT type="text/javascript"> //var comActiveX; try { //comActiveX = new ActiveXObject("HttpAsy.CollectGood"); } catch (e) { // alert("沒有注冊好"); } comActiveX.attachEvent("eventsGet",function(msg){alert(msg)}) comActiveX.AsyncGet("http:/www.baidu.com",5);
當運行后就會 彈出 百度源代碼
這就實現了異步回調
http://files.cnblogs.com/echosong/http.rar 完整demo下載(先點reg.bat先注冊dll)