关于winapi:使用ExitThread关闭线程-C

Closing thread using ExitThread - C

我有一个简单的程序,该程序创建一个线程,循环20次,然后进行调用以关闭自身并执行必要的清理。

当我调试程序时,它到达ExitThread();方法并暂停,忽略printf();我已经设置了它,以向我表示已关闭。

这是正常现象还是我忘了做什么?我是使用C进行线程处理的新手。

主要()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void main()
{
    Time t;
    int i = 0;

    StartTimer();

    for(i = 0; i < 20; i++)
    {
        t = GetTime();
        printf("%d.%.3d\
"
, t.seconds, t.milliseconds);
        Sleep(100);
    }
    StopTimer();
}

线程创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void StartTimer()
{
    DWORD threadId;
seconds = 0;
milliseconds = 0;

// Create child thread
hThread = CreateThread(
    NULL,       // lpThreadAttributes (default)
    0,          // dwStackSize (default)
    ThreadFunc, // lpStartAddress
    NULL,       // lpParameter
    0,          // dwCreationFlags
    &threadId   // lpThreadId (returned by function)
    );

// Check child thread was created successfully
if(hThread == NULL)
{
    printf("Error creating thread\
"
);
}
}

螺纹关闭

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void StopTimer()
{
    DWORD exitCode;

    if(GetExitCodeThread(hThread,&exitCode) != 0)
    {
        ExitThread(exitCode);  
        printf("Thread closed");

        if(CloseHandle(hThread))
        {
            printf("Handle closed");
        }
    }
}

编辑:

我已经意识到ExitThread()会停止正在执行的线程,因此我尝试使用其他方法来停止计时器,但是我仍然得到相同的结果。

1
2
3
4
void StopTimer()
{    
    WaitForSingleObject(hThread,INFINITE);
}

解:

程序在WaitForSingleObject()调用处停止并且无论进行多长时间都没有进行的原因是因为它正在等待的操作具有无限循环。

它将等待无限循环完成,而不是最好的事情。将WaitForSingleObject()的延迟更改为更合理的延迟(例如100)可以使程序正常运行。

感谢所有的投入。


是的,这是"正常的",通过调用ExitThread,您可以告诉Windows您已经完成了该调用线程,因此其余代码不会被调用。这有点像调用exit(0)。

我个人不会这样使用它。其余代码都可以,您正在正确清理线程,只需正常退出线程功能即可。


由于您是在主线程的上下文中调用StopTimer的,因此当它调用出口线程时,它将结束主线程并与之一起结束进程。


ExittThread函数会立即终止CALLING线程。


这是正常的,因为ExitThread实际上退出了当前线程,所以它将永远不会返回,并且以下指令也将不会执行。

顺便说一句,您永远不要直接调用ExitThread(除非您真的知道自己在做什么):您只需要从线程函数中返回即可。

然后,如果使用C运行时库,则不应使用原始线程API,而应使用C运行时库功能,如_beginthread和_beginthreadex。


您可以在ThreadFunc的开头创建一个事件,例如hStop,然后在每个循环中立即等待该事件。那么您可以在主线程中使用SetEvent()来要求线程停止。

注意对于链接到LIBCMT.LIB的可执行文件,请不要调用Win32 ExitThread API;否则,请执行以下步骤。这样可以防止运行时系统回收分配的资源。 _endthread和_endthreadex回收分配的线程资源,然后调用ExitThread。