2

我必须创建一个应用程序,我必须在其中创建多个线程。所以我想尝试制作一个函数并将其传递给不同的线程。最初,我创建了两个线程并声明了一个要传递给它们的函数。我要做的就是将不同的整数传递给这些线程并将其显示在线程函数中,这是我的代码:

DWORD WINAPI Name(LPVOID lpParam)
{
    int *Ptr=(int*)lpParam;

    for(int j=0;j<2;j++)
    {
        cout<<"Thread"<<endl;
        cout<<*Ptr<<endl;
    }

    return 0;
}
int main()
{
    int a=10,b=15,c=25;
    HANDLE thread1,thread2;
    DWORD threadID,threadID2;
    thread2= CreateThread(NULL,0,Name,LPVOID(a),0,&threadID2);
    thread1= CreateThread(NULL,0,Name,LPVOID(b),0,&threadID);

    for(int i=0;i<5;i++)
    {
        cout<<"Main Thread"<<endl;
    }

    if(thread1==NULL)
    {
        cout<<"Couldn't Create Thread:("<<endl;
        exit(0);
    }
    if(thread2==NULL)
    {
        cout<<"Couldn't Create Thread:("<<endl;
        exit(0);
    }
    return 0;
}

但这段代码运行不正常,即编译正常,开始正常但随后出现调试错误。有人可以让我知道我的错误以及如何纠正它,因为能够将一个函数用于多个线程将对我非常有帮助。

4

3 回答 3

3

等待您的子线程返回。做这个:

int main()
{
    int a=10,b=15,c=25;
    HANDLE thread[2];
    DWORD threadID,threadID2;
    thread[1]= CreateThread(NULL,0,Name,LPVOID(a),0,&threadID2);
    thread[0]= CreateThread(NULL,0,Name,LPVOID(b),0,&threadID);

    for(int i=0;i<5;i++)
    {
        cout<<"Main Thread"<<endl;
    }

    if(thread[0]==NULL)
    {
        cout<<"Couldn't Create Thread:("<<endl;
        exit(0);
    }
    if(thread[1]==NULL)
    {
        cout<<"Couldn't Create Thread:("<<endl;
        CloseHandle(thread[0]);
        exit(0);
    }
    WaitForMultipleObjects(2, thread, TRUE, INFINITE);
    CloseHandle(thread[0]);
    CloseHandle(thread[1]);
    return 0;
}

当线程终止时,会发出线程句柄的信号(请参阅CreateThread)。

于 2013-05-02T10:51:56.787 回答
2

您正在将函数中的局部变量的地址传递到您的线程中。当线程开始运行你的函数时,可能已经退出 main 了。因此,线程将尝试访问堆栈中不再存在的变量,因此将读取一些随机值,当您尝试将其作为指针取消引用时,可能会崩溃。

你主要需要等待。对于一个简单的测试,只需在它退出之前放入 Sleep(10000) 或其他东西。显然,这对真正的程序没有用。

于 2013-05-02T10:32:37.720 回答
1

总结评论:有两种方法可以传递数据。要么直接在 void 指针内部,因为“void 指针”是一个整数类型,因此可以表示整数(但它不一定具有与 相同的宽度int),或者间接通过传递您关心的事物的实际地址。

方法一(传值):

DWORD WINAPI Name(LPVOID lpParam)
{
    intptr_t n = reinterpret_cast<intptr_t>(lpParam);
    // ...
}

int main()
{
    intptr_t a = 10;

    thread1 = CreateThread(NULL, 0, Name, reinterpret_cast<void *>(a), 0, &threadID);
    // ...                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}

对于这种方法,我们使用整数类型intptr_t,其宽度与 相同void *。我们使用 reinterpret-casts 来存储和检索任意整数值。


方法2(传递指针):

DWORD WINAPI Name(LPVOID lpParam)
{
    T * p = static_cast<T *>(lpParam);

    // ...  use *p ...
}

int main()
{
    T thing_I_care_about;

    thread1 = CreateThread(NULL, 0, Name, &thing_I_care_about, 0, &threadID);
    // ...                                ^^^^^^^^^^^^^^^^^^^
}

这是更通用的方法,但需要thing_I_care_about保持活动状态,并且它成为一个脆弱的共享状态,因此生命周期管理和同步成为问题。请注意,任何对象指针都可以隐式转换为void *,因此不需要在调用站点进行强制转换。


最后,正如其他人评论的那样,不要忘记加入或分离您的线程。

于 2013-05-02T11:34:18.557 回答