【问题标题】:Passing parameters to _beginthreadex将参数传递给 _beginthreadex
【发布时间】:2011-05-11 17:16:09
【问题描述】:

我正在尝试使用 _beginthreadex 进行一些基本的并行化,并按照我给出的示例传递参数,但它不起作用。

有什么想法吗?

#include <iostream> 
#include <process.h>



void MyThread(void *data)
{
    std::cout << "Hello World!"; 
}

int main()
{
    _beginthreadex(NULL, 0, MyThread, NULL, 0, NULL); 
    while(true);
}

编辑:

为什么不能将 NULL 作为参数传递? (因为函数无论如何都没有参数?)

将 NULL 作为参数列表传递给 _beginthread 效果很好。

【问题讨论】:

  • 它有什么作用?怎么不行?
  • 错误 C2664: '_beginthreadex' : 无法将参数 3 从 'void (__cdecl *)(void *)' 转换为 'unsigned int (__stdcall *)(void *)'
  • 显然你的函数需要返回一个整数。查看我编辑的帖子。

标签: c++ windows multithreading


【解决方案1】:

您的代码中有两个错误,它们都与线程函数的参数无关 --- NULL 对此很好,正如您所猜测的那样。

问题出在线程函数的签名中,您得到的错误指出了这一点。首先,它必须是一个__stdcall 函数,其次它必须返回一个unsigned int。您的函数是 __cdecl 并返回 void

unsigned __stdcall MyThread(void *data)
{
    std::cout << "Hello World!"; 
    return 0;
}

应该为你解决问题。

【讨论】:

    【解决方案2】:

    显然在您的代码中您没有传递任何参数。要传递变量,您必须执行以下操作(例如):

    #include <iostream> 
    #include <process.h>
    
    void MyThread(void *data)
    {
        int x = static_cast<int*>(data);
        std::cout << "Hello World! " << x; 
    }
    
    int main()
    {
        int x = 10;
        _beginthreadex(NULL, 0, MyThread, &x, 0, NULL); 
        while(true);
    }
    

    更新:由于您稍后发布了编译问题: 显然你的线程函数需要返回一个整数:

    int MyThread(void *data)
    {
        std::cout << "Hello World!"; 
        return 0;
    }
    

    【讨论】:

    • 但是由于 MyThread 不接受任何参数,所以不需要传递变量?
    • A 它确实有一个参数列表 a void* 和 B 是,因为 NULL 是一个有效的 void * 值。
    • 当然,您编写的代码是可以接受的并且可以编译的。但我以为你想传递一个参数,不是吗?
    • 应该 int main() 是: int* x = new int(10);和 _beginthreadex(NULL, 0, MyThread, x, 0, NULL);???使用 MyThread 将其转换为 int* 指针?
    • 在这种情况下不必使用动态分配,因为i 保证在线程期间持续存在。
    【解决方案3】:

    您通过第四个参数传递数据。这会传递一个指向i 的指针:

    unsigned __stdcall thread(void *arg)
    {
        int *iptr = (int*)arg;
        ...
    }
    
    int i;
    _beginthreadex(0, 0, thread, &i, 0, 0);
    

    请注意,我在这里使用的线程函数签名与您使用的不同:我返回一个 unsigned 并使用 __stdcall 调用约定——这是 _beginthreadex 期望的签名。

    根据您要执行的操作,VC++ 中的新 Concurrency Runtime 功能可能比显式管理您自己的线程更易于使用。

    编辑回应问题编辑:

    您可以传递任何有效的 void 指针,包括 NULL。如果你这样做,你甚至可以省略参数的名称,因为你没有使用它:

    unsigned __stdcall thread(void*)
    {
        ...
    }
    
    _beginthreadex(0, 0, thread, 0, 0, 0);
    

    【讨论】:

    • 您的函数没有返回任何值。这肯定会导致编译器警告/错误。
    • 是的,为了简洁起见,我把它省略了。你当然也不应该尝试从函数外部调用_beginthreadex
    【解决方案4】:

    _beginthreadex 的参数必须是具有__stdcall 调用约定的函数。你的函数有__cdecl。在正确的位置简单地插入__stdcall 即可解决问题。

    void __stdcall MyThread(void *data)
    {
        std::cout << "Hello World!"; 
    }
    

    【讨论】:

    • 我添加了它,但我仍然收到此错误 - 错误 C2664: '_beginthreadex' : 无法将参数 3 从 'void (__stdcall *)(void *)' 转换为 'unsigned int ( __stdcall *)(void *)'
    【解决方案5】:

    The fourth parameter in _beginthreadex(NULL, 0, MyThread, NULL, 0, NULL) are arguments to the function MyThread

    现在你将 NULL 传递给它,所以 void* data 必须得到一个 NULL 指针

    struct X  
    {  
        int a;  
        int b;  
    };
    
    X* x = (X*)malloc(sizeof(X));  
    
    x->a = 5;  
    x->b = 6;  
    _beginthreadex(NULL, 0, MyThread, NULL, x, NULL);
    

    以上代码会将指针x 传递给函数MyThread()
    请注意X,因为它最好由malloc 或new 分配。在使用线程连接之前不要在堆栈上创建它

    【讨论】:

    • NULL 是一个有效的 void* 类型不是吗?
    • @Atomerz:是的,你是对的。我误解了问题,没有看到问题的编辑部分
    猜你喜欢
    • 2014-11-12
    • 1970-01-01
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 2013-11-19
    相关资源
    最近更新 更多