【问题标题】:WIN32 Thread Program IssueWIN32 线程程序问题
【发布时间】:2017-05-05 05:29:44
【问题描述】:

这是我第一次处理线程。

当我在没有GetCurrentThreadId() 函数的情况下运行程序时,它的执行没有任何问题。

当我添加那行代码时,它仍然会执行,但一旦到达末尾就会崩溃。这是为什么呢?

#include <Windows.h>
#include <stdio.h>
#include <conio.h>


static int tix[500];
static int done = 0;
HANDLE ghSemaphore;

DWORD WINAPI ThreadFunction();

int main(void)
{
    DWORD threadID1, threadID2, threadID3, threadID4;
    HANDLE hThread1, hThread2, hThread3, hThread4;

    for (int i = 0; i < 500; i++) //initialize array
    {
        tix[i] = 0;
    }

    ghSemaphore = CreateSemaphore(NULL, 1, 10, NULL);

    hThread1 = CreateThread(NULL, 0, ThreadFunction, NULL, 0, &threadID1);
    hThread2 = CreateThread(NULL, 0, ThreadFunction, NULL, 0, &threadID2);
    hThread3 = CreateThread(NULL, 0, ThreadFunction, NULL, 0, &threadID3);
    hThread4 = CreateThread(NULL, 0, ThreadFunction, NULL, 0, &threadID4);

    //printf("The thread ID: %d.\n", threadID1);
    //printf("The thread ID: %d.\n", threadID2);
    //printf("The thread ID: %d.\n", threadID3);
    //printf("The thread ID: %d.\n", threadID4);

    if (done = 1)
    {
        CloseHandle(hThread1);
        CloseHandle(hThread2);
        CloseHandle(hThread3);
        CloseHandle(hThread4);
    }

    for (int j = 0; j < 500; j++)
    {
        if (tix[j] = 0)
        {
            printf("not sold");
        }
        else if (tix[j] = 1)
        {
            printf("sold");
        }
    }

    return 0;
}

DWORD WINAPI ThreadFunction()
{
    WaitForSingleObject(ghSemaphore, 0);

    printf("current thread running : %d\n", GetCurrentThreadId());

    int i = 0;
    if (done != 0) // if loop to test wether or not the array is full
    {
        while (tix[i] = 1) //traverse the array to find a open spot
        {
            i++;
        }
        tix[i] = 1;

    }
    if (i == 499) //if i is 499, set test variable to 1
    {
        done = 1;
        return 0;
    }

    ReleaseSemaphore(ghSemaphore, 1, NULL);
}

【问题讨论】:

  • 崩溃时的错误信息是什么?
  • 您的线程函数的签名不正确,因此您可能正在破坏堆栈。不要忽略编译器警告。此外,if (done = 1)if (tix[j] = 1) 将始终为真。我建议你在尝试多线程之前掌握基本的 C。
  • 您的代码永远不会关闭线程句柄。在函数结束时,您需要 WaitForMultipleObjects 并确保在关闭句柄之前所有线程都已执行完毕。不用说,变量done在多线程程序中是无稽之谈。
  • @Lundin:您确实不必必须等待线程运行完成才能关闭其句柄。如果您的代码不需要它,它可以在CreateThread 返回后立即关闭句柄。
  • @IInspectable 然而,在清理和关闭主进程之前等待所有线程完成是一个好习惯。

标签: c multithreading winapi


【解决方案1】:

您的线程函数的签名不正确。线程接受一个PVOID 上下文参数:

DWORD WINAPI ThreadProc(
  _In_ LPVOID lpParameter
);

您的线程可以在不释放信号量的情况下退出。此外,由于您使用大于线程数量的值对其进行了初始化,并且从不检查WaitForSingleObject 结果,因此不提供同步,并且多个线程将以不一致的方式修改共享缓冲区。更糟糕的是 - 没有什么比 ThreadFunction 更早地阻止您的程序主线程退出。

在你的线程函数末尾没有返回语句,所以这是一个未定义的行为。实际上,您的代码甚至可以编译是一个很大的奇迹。整个多线程方法是不正确的,必须从头开始重新制作。

【讨论】:

  • 这种情况已经很久没有了。如果是这种情况,那么 Windows 线程池将无法工作。不过答案的后半部分很好。
  • 您对 beginthread 的评论就像 20 岁。 IIRC 这是因为 Visual Studio 编译器中的错误,而不是 Windows API 中的错误。
  • 好吧。 MSDN 仍然有这个建议。我是谁来反驳他们?)
  • 删除了过时的信息。谢谢@DavidHeffernan
  • 是的,MSDN 仍然生活在过去并迎合 msvc 6 用户
猜你喜欢
  • 2012-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多