in32应用程序中,这会导致程序终止运行,指示灯信号永远不会得到释放。这就造成了等待该指示灯信号的其它线程会永远等待下去。而将ReleaseSemaphore放在finally程序段内则从根本上保证了不论何种情况出现指示灯信号都会得到释放。
如果中断处理句柄能够处理由于无效内存读写而造成的程序中断,我们就完全有理由相信它能够处理诸如setjump/longjump、break和continue这类的中断转移。事实也正是这样。
2.3、小测试
下面一个例子(见清单五)请读者猜测一下函数FuncaDoodleDoo的返回值。(
答案为14)
DWORD FuncaDoodleDoo(void) {
DWORD dwTemp = 0;
while (dwTemp 〈 10) {
__try {
if (dwTemp == 2)
continue;
if (dwTemp == 3)
break;
}
__finally {
dwTemp++;
}
dwTemp++;
}
dwTemp += 10;
return (dwTemp);
}
FuncaDoodleDoo函数代码
虽然中断处理句柄能够接收出现在try程序段内的绝大部分异常情况,但是如果线程或进程中断执行的话,则finally程序段内的代码不会被执行。调用ExitThread或ExitProcess就会立即造成线程或进程的中断,而不会执行finally程序段。另外,如果其它的应用程序调用ExitThread或ExitProcess而造成你的线程或进程中断,你程序中的finally程序段也不会被执行。一些C函数如abort会调用ExitProcess,也会导致你的finally程序段不被执行。对此你无能为力。但你可以防止你自己提早调用ExitThread或ExitProcess。
2.4、应用例子
我们已经讨论了中断处理句柄的句法及语法。现在我们进一步讨论如何利用中断处理句柄来简化一个比较复杂的编程问题。
首先让我们来看一个没有使用中断处理句柄的例子,程序源代码见例6。
BOOL Funcarama1 (void) {
HANDLE hFile = INVALID_HANDLE_VALUE;
LPVOID lpBuf = NULL;
DWORD dwNumBytesRead;
BOOL fOk;
hFile = CreateFile("SOMEDATA.DAT", GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
return (FALSE);
}
lpBuf = VitualAlloc(NULL, 1024, MEM_COMMIT, PAGE_READWRITE);
if (lpBuf == NULL) {
CloseHandle(hFile);
return (FALSE);
}
fOk = ReadFile(hFile, lpBuf, 1024, &dwNumBytesRead, NULL);
if (!fOk || (dwNumBytesRead == 0)) {
VirtualFree(lpBuf, MEM_RELEASE | MEM_DECOMMIT);
CloseHandle(hFile);
return (FALSE);
}
// Do some calculation on the data.
.
.
.
// Clean up all the resources.
VirtualFree(lpBuf, MEM_RELEASE | MEM_DECOMMIT);
CloseHandle(hFile);
return (TRUE);
}
例6 没有使用中断处理句柄的Funcarama1函数代码
在上例Funcarama1函数中,所有的错误诊断使得该函数难以理解、维护和修改。当然,我们可以对Funcarama1函数进行一些改动,使其易于理解(见例7)。
BOOL Funcarama2 (void) {
HANDLE hFile = INVALID_HANDLE_VALUE;
LPVOID lpBuf = NULL;
DWORD dwNumBytesRead;
BOOL fOk, fSuccess = FALSE;
hFile = CreateFile("SOMEDATA.DAT", GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
lpBuf = VitualAlloc(NULL, 1024, MEM_COMMIT, PAGE_READWRITE);
if (lpBuf != NULL) {
fOk = ReadFile(hFile, lpBuf, 1024, &dwNumBytesRead, NULL);
if (fOk || (dwNumBytesRead != 0)) {
// Do some calculation on the data.
.
.
.
fSuccess = TRUE;
}
}
VirtualFree(lpBuf, MEM_RELEASE | MEM_DECOMMIT);
}
CloseHandle(hFile);
return (fSuccess);
}
例7 没有使用中断处理句柄的Funcarama2函数代码
虽然函数Funcarama2容易理解,但是仍然难于维护和修改。
现在让我们来利用中断处理句柄