【问题标题】:Efficiently passing parameters to function in another thread in C++在 C++ 中有效地将参数传递给另一个线程中的函数
【发布时间】:2012-02-18 03:15:50
【问题描述】:

据我所知,可以使用指向结构的指针。但我想知道,有没有更有效或更优雅的方式来做到这一点?至少在使用结构体的时候,不容易看出函数使用了哪些参数。

感谢任何有见地的回答。

【问题讨论】:

  • 你能详细说明一下吗? “将参数传递给另一个线程中的函数”是什么意思?
  • 你想做什么?函数定义不在一个或另一个线程上,它可以在任何线程上运行;出现线程问题的一件事是,它是否正在修改一个线程上的数据,而该线程也正在被另一个线程修改。您可以访问另一个线程正在访问的数据结构,但您必须知道正确访问和修改它所需的确切安全措施;最好将功能包装在一个函数中,这样您就不必记住适当的保护措施,或者担心破坏它们。
  • c++(c++11 之前)不了解线程。你用的是什么多线程系统? “将参数传递给函数”是什么意思?
  • 您不能在“另一个线程”中调用或返回函数。您所能做的就是向另一个线程发出信号,告知在某个地方有一些数据可以访问,因此通常依赖于结构指针或实例引用——这些东西可以很容易地排队,或者以其他方式与线程通信,而无需扩展锁定,可以携带输入/输出/状态等数据,并可以指示线程对其进行处理,例如。用数据调用一些函数。如果您使用有意义的成员名称,通常会很清楚发生了什么。
  • 假设我们只有一个线程A,我们可以调用一个函数foo(int bar1, int bar2);直接在这个线程中。现在想想另一个线程 B,如果你想在那里调用 foo 但你需要从线程 A 传入的 bar1、bar2,你会怎么做?我的问题是如何有效地做到这一点?线程安全是我们稍后可以弄清楚的另一件事。

标签: c++ multithreading parameter-passing


【解决方案1】:

这是一个使用 WIN32 API 的小例子:

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

struct PARAMS
{
    int i;
    char* msg;
};

DWORD WINAPI myThread(void* parameter)
{
    PARAMS* params = (PARAMS*)parameter;
    printf("Received parameters: i = %d, msg = '%s'\n", params->i, params->msg);
    return 0;
}

int main(int argc, char* argv[])
{
    char msg[] = "Hi there.";
    PARAMS params;
    params.i = 1;
    params.msg = msg;

    HANDLE threadHandle = CreateThread(NULL, 0, myThread, &params, 0, NULL);
    WaitForSingleObject(threadHandle, INFINITE);

    return 0;
}

您说,“不容易看到函数使用的参数是什么”。好吧,这取决于情况。如果您认为它不够“优雅”,您至少应该在那里留下一些有用的评论......如果您使用良好的命名并尝试编写代码,即自我记录,那么使用结构就可以了.

这是一个包装 CreateThread 的示例,这样使用您的代码的程序员就不必知道您正在使用某种结构:

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

class MyWrapper
{
private:
    struct PARAMS
    {
        int i;
        char* msg;
    };

    static DWORD WINAPI myThread(void* parameter)
    {
        PARAMS* params = (PARAMS*)parameter;
        printf("Received parameters: i = %d, msg = '%s'\n", params->i, params->msg);
        delete params;
        return 0;
    }

public:
    HANDLE createThread(int i, char* msg)
    {
        PARAMS* params = new PARAMS;
        params->i = i;
        params->msg = msg;

        return CreateThread(NULL, 0, MyWrapper::myThread, params, 0, NULL);
    }
};

int main(int argc, char* argv[])
{
    MyWrapper mw;
    char msg[] = "Hi there.";

    HANDLE threadHandle = mw.createThread(1, msg);
    WaitForSingleObject(threadHandle, INFINITE);

    return 0;
}

【讨论】:

  • 我想你知道我在说什么。 :) 使用 CreateThread 意味着我需要为每个函数调用创建一个线程,这对性能不利。其次,如果使用了 void* 参数,我们在编译时无法检查很多东西,例如传入的参数是否准确,所以也不优雅。
  • @echo:CreateThread函数不应该用来实现函数调用,它是故意创建一个新线程。通常它用于并行执行某些任务,从而提高性能。 if void* parameters is used, we cannot check lot of things during compile time, for example, if exact number of parameters are passed in - 如果它打算供其他人使用(库、API ...),您应该创建将“隐藏”您的内部实现的包装器。
【解决方案2】:

这是一个小例子,如果你想在 Win32 API 中将单个参数传递给线程函数

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

DWORD WINAPI funHello(void *x)
{
    int c = (int*)x;
    printf("\n Thread No: %d\n",c);
    // Do some work , call some function, etc.
    return 0;
}

int main()
{
    HANDLE  myhandle;
    DWORD threadId;
    int c = 1;
    myhandle = CreateThread(NULL, 0, funHello, (void *)c, 0, &threadId);
    if (myhandle == NULL)
    {
        printf("Create Thread Failed. Error no: %d\n", GetLastError);
    }
    WaitForSingleObject(myhandle, INFINITE);
    printf("\n Main Hello...\n");
    CloseHandle(myhandle);
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-05
    • 2012-09-25
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 2012-10-17
    相关资源
    最近更新 更多