使用InternetOpenUrl挂起的一个解决方案
来源:互联网 发布:非嵌入式软件即征即退 编辑:程序博客网 时间:2024/06/06 04:01
在某个同事留下的网络操作代码中,如果用户试图从网络打开一个实际并不存在的URL, 走到InternetOpenUrl这步,应用程序就一命呜呼了。这个API并没有按照文档上说的那样返回一个NULL给文件HANDLE,而是完全停止响应。他尝试使用InternetSetOption来设置超时的时限,代码里这样写
DWORD n = 10000;
InternetSetOption(p->Internet, INTERNET_OPTION_CONNECT_TIMEOUT, &n, sizeof(n));
但没有实际效果。从后文可以猜测,InternetOpenUrl再去调用了网络的IO处理,在IO处理中被卡死,罪过似乎并不在InternetOpenUrl和wininet.dll这层上.
于是他在前面某次工作记录里说已经解决了这个问题,然后又被测试组骂回来说没效果. 我搜到了开源代码里一个很好的算法, 自己测试了下,的确有效。让我们来看下它的算法,确实很精妙. 整个算法的核心是用异步方式来处理wininet.dll提供的那些函数
具体实现代码如下:
(1) 首先, 在InternetOpen时修改了参数
它用的是 InternetOpen(T("MyApp"), p->AccessType, NULL,NULL, INTERNET_FLAG_ASYNC);
而会卡死的情况下用的是 InternetOpen(T("AmoiPlayer"),INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0);
前面几个参数不是影响该性能的关键,关键点在最后一个参数上: INTERNET_FLAG_ASYNC. 在文档里对这个参数的解释是 Makes only asynchronous requests on handles descended from the handle returned from this function. 写得有些晦涩. 实际效果就是如果在InternetOpen中设置为INTERNET_FLAG_ASYNC, 那么在InternetOpenUrl时就会立刻返回, 如果为NULL就必须有具体的返回值才肯RETRUN.
(2) 注册一个CALLBACK函数 InternetSetStatusCallback(p->Internet, InternetCallback)
因为我们OpenURL操作会立刻返回了,那么什么时候能得到有效或无效的HANDLE呢? 这就需要一个CALLBACK来做这件事情. 这里当然有必要看下这个CALLBACK函数里做了什么
static void CALLBACK InternetCallback(HINTERNET hInternet,
DWORD dwContext,
DWORD dwInternetStatus,
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength)
{
if (dwInternetStatus == INTERNET_STATUS_REQUEST_COMPLETE)
{
INTERNET_ASYNC_RESULT *Result = (INTERNET_ASYNC_RESULT*)lpvStatusInformation;
http *p = (http*)dwContext;
p->CompleteResult = Result->dwResult;
SetEvent(p->Complete);
}
}
当等到INTERNET_STATUS_REQUEST_COMPLETE通知的时候, 把RESULT获取下来放在p->CompleteResult里面,然后SetEvent. 也就是说系统CALLBACK线程和其他什么线程进行通信了
(3) 在InternetOpenUrl的时候代码如下:
Result = (DWORD)InternetOpenUrl(p->Internet, URL, s, (DWORD)-1, INTERNET_FLAG_NO_CACHE_WRITE|Secure, (DWORD)p);
p->Handle = (HANDLE)Pending(p, Result , 30);
if (Result || GetLastError() != ERROR_IO_PENDING)
{
p->Handle = Result;
}
else
{
p->Pending = 1;
if ( WaitForSingleObject(p->Complete,300000) == WAIT_OBJECT_0 )
{
p->Pending =0;
p->Handle = p->CompleteResult;
}
else
{
p->Handle = NULL;
}
}
代码中把流程图中的左边线程, 从调用API触发CALLBACK开始, 到底端取得HANDEL这块算法封装为一个函数, 可以被其他对wininet.dll接口函数的操作共用, 如InternetReadFile等.
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/li_guotao/archive/2009/02/20/3915102.aspx
- 使用InternetOpenUrl挂起的一个解决方案
- 使用InternetOpenUrl挂起的一个解决方案
- 使用InternetOpenUrl挂起的一个解决方案
- 使用InternetOpenUrl挂起的一个解决方案
- InternetOpenUrl函数 的应用
- flash builder 安装时提示挂起的解决方案(使用于adobe 的各产品)
- InternetOpenUrl()在DllMain中卡死的问题
- 一个解决虚拟机无法挂起的方法
- 一个可安全挂起,恢复的线程
- 挂起一个正在运行的进程
- SQL安装挂起解决方案
- SqlServer安装过程的挂起问题的解决方案
- SqlServer安装过程的挂起问题的解决方案
- SqlServer安装过程的挂起问题的解决方案
- 安装SqlServer2000出现"有挂起的操作"的解决方案
- 安装sql2000,提示有程序以挂起的解决方案
- SQL SEVER 2000安装的挂起问题及相关解决方案
- SQL Server 2000安装时挂起的解决方案
- 菜鸟学堂之不传秘术:应用程序无法启动,因为应用程序的并行配置不正确]这个问题的实际解决办法
- SWFupload在IE9中选择文件按钮无法点击bug解决方法
- POJ 1325 Machine Schedule
- NET WORK
- 更改状态栏颜色
- 使用InternetOpenUrl挂起的一个解决方案
- struts2 OGNL ValueStack概念理解 # % $ 的区别
- IOS7之后的导航栏遮盖问题
- C++队列数组实现
- IO、关键字与异常系统总结
- TRANSFORM_TEX
- 河南2014 省赛 世界之威
- [Android个人理解(六)]使用include标签的注意事项
- android在eclipse下的环境搭建