前言:
由于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)