正确终止多线程Windows控制台应用程序

时间:2012-03-20 23:36:27

标签: c windows winapi

以下是我正在从一个更大的项目中汇总的概念的简要证明。该项目具有使用CreateThread创建的工作线程,该线程监视目录以进行更改。我有一些清理代码需要像关闭句柄一样运行并释放一些内存。

应用程序不作为后台进程或服务运行。它通过命令行运行并运行,直到用户关闭命令窗口或按Ctrl-C

有更好的方法吗?我尝试使用atexit但显然在进程被杀死时没有被调用。

请注意,我使用的是C,而不是C ++,并且不使用MFC,AFX或Windows API以外的任何其他API。根据评论,我想另一部分是如何在多线程环境中正确终止应用程序?这没关系,还是应该在ExitProcess内拨打thread_func

更新: 我已经更新了Luke在下面的注释,设置了一个标志,表明应用程序正在终止。我还将其更改为使用atexit来调用清理函数而不是直接调用它。

#include <stdio.h>
#include <windows.h>

HANDLE thread_handle = INVALID_HANDLE_VALUE;
BOOL time_to_quit = FALSE;

DWORD WINAPI thread_func(LPVOID lpvd)
{
  fwprintf(stdout, L"thread running...\n");
  while (!time_to_quit)
  {
    /* do stuff */
    Sleep(10);
  }

  return 0;
}

void cleanup()
{
  /* clean up code here that needs to be run at exit */
  fwprintf(stdout, L"cleaning up...\n");
  CloseHandle(thread_handle);
}

BOOL WINAPI console_handler(DWORD event)
{
    time_to_quit = TRUE;
    return FALSE;
}

int wmain(int argc, wchar_t* argv[])
{
  DWORD thread_id = 0;

  thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_func, NULL, 0, &thread_id);
  if (thread_handle != NULL) 
  {
    atexit(cleanup);
    fwprintf(stdout, L"thread created...\n");
    SetConsoleCtrlHandler((PHANDLER_ROUTINE)console_handler, TRUE);
    WaitForSingleObject(thread_handle, INFINITE);
  }

  return 0;
}

1 个答案:

答案 0 :(得分:0)

从一般意义上讲,您可以使用 signal()

#include <stdio.h>
#include <stdlib.h>    /* exit() */
#include <signal.h>    /* signal() */
#include <unistd.h>    /* sleep() */

void my_sigtrap(int sig)
{
    printf ("\n"
        "Signal %d == %d received.\n"
        "Bye bye\n",
        sig, SIGINT);
    exit(0);
}

int main(void)
{
    void (*orig_sig_fun)(int);

    orig_sig_fun = signal(SIGINT, my_sigtrap);

    if (orig_sig_fun == SIG_IGN) {
        printf("Ignored by default\n");
        signal(SIGINT, SIG_IGN);
    } else if (orig_sig_fun == SIG_DFL) {
        printf("Signal handled by default.\n");
    } else if (orig_sig_fun == SIG_ERR) {
        perror("Failed to set signal\nNo trap\n --");
    }

    setbuf(stdout, NULL); /* Turning off buffering */
    putchar('.');
    while (1) {
        putchar('.');
        sleep(1);
    }

    return 0;
}