我正在使用InternetSetStatusCallback来传输数据:
CallbackPointer = InternetSetStatusCallback(SessionHandle,
(INTERNET_STATUS_CALLBACK)CallBack);
尽管流量数据每250ms发送一次,但有时会在退出之前再次调用下面的CallBack函数,因此程序应该有足够的时间来处理数据。
bool InsideFunc = false;
VOID CALLBACK
CallBack(
__in HINTERNET hInternet,
__in DWORD_PTR dwContext,
__in DWORD dwInternetStatus,
__in_bcount(dwStatusInformationLength) LPVOID lpvStatusInformation,
__in DWORD dwStatusInformationLength
)
{
if (InsideFunc)
{
// should not happen
}
InsideFunc = true;
cOandaFeed* oandaFeed = (cOandaFeed*)dwContext;
ASSERTRETURN(oandaFeed);
ASSERT(dwContext);
switch (dwInternetStatus) {
case INTERNET_STATUS_HANDLE_CREATED:
oandaFeed->StatusHandle = lpvStatusInformation;
break;
case INTERNET_STATUS_REQUEST_COMPLETE:
if (oandaFeed->State == cOandaFeed::OPENING)
oandaFeed->StartFeeding();
break;
case INTERNET_STATUS_RESPONSE_RECEIVED:
if (oandaFeed->State == cOandaFeed::FEEDING) {
oandaFeed->ReadFile(); // this is where I call InternetReadFileEx
oandaFeed->CollectAndForwardChunks();
}
break;
case INTERNET_STATUS_HANDLE_CLOSING:
oandaFeed->SetState(cOandaFeed::IDLE);
break;
case INTERNET_STATUS_RECEIVING_RESPONSE:
break;
}
InsideFunc = false;
}
因此程序正确初始化并获得INTERNET_STATUS_RECEIVING_RESPONSE和INTERNET_STATUS_RESPONSE_RECEIVED等状态响应。到现在为止还挺好。但是下一次迭代出错了,InternetReadFileEx调用两次并获取错误消息,一个用于挂起的IO,另一个用于InternetReadFileEx的内部错误。下一轮再好,然后是错误。
我做了“bool insideFunc”技巧,看看我怀疑是否正在发生什么,是的,有时候“调用”在设置之前是真的,所以有时它甚至在它结束之前被调用。我只想在INTERNET_STATUS_RESPONSE_RECEIVED上阅读我的消息,但有时CallBack()会在它完成之前再次被调用,并且InternetReadFileEx会在错误的时间发生,导致它返回错误代码997和12004。
我该如何解决?
我能够很容易地解决这个问题。问题是我在交换机的INTERNET_STATUS_RESPONSE_RECEIVED情况下保持了我的ReadFile()调用。它导致了麻烦,因为在我的ReadFile()内部调用InternetReadFileEx()时,通过回调发送状态,导致再次对ReadFile()进行递归调用。
因此,第一个ReadFile()调用导致997:ERROR_IO_PENDING,而第二个调用(导致但递归)导致12004:内部错误。
解决方案:在我将ReadFile()移动到交换机中的INTERNET_STATUS_REQUEST_COMPLETE情况后,我只得到了ERROR_IO_PENDING,因为我们没有在ReadFile()中获得具有此状态的CallBack。在InternetReadFileEx()返回很久之后,我们异步地获得此状态。 ERROR_IO_PENDING是正常的:
注意GetLastError代码ERROR_IO_PENDING不是失败;它指定读取操作异步完成等待完成。
引自qazxsw poi
流媒体工作
这是流媒体在Oanda的工作方式,但我想这是常见的做法?
谢谢大家的回复。