关于C#:将普通数据传递给pthread void *

Passing normal data to pthread void *

pthread函数采用void *参数。 如何发送普通结构而不是指针?

我想将非指针结构发送给一个pthread函数。

我也想发送一个指向void *函数的指针,这是怎么做的? 可以将任何指针发送到void *函数吗?


不可能;您必须发送一个指针。但是,void *可以指向任何内容。如果您的struct变量名为foo,则可以简单地将其作为(void *) &foo传递,并且在函数内部,可以将其强制转换回例如。 struct Foostruct Foo * fooPtr = (struct Foo *) param;struct Foo foo = *((struct Foo *) param);一起使用。

编辑:正如注释中提到的@forsvarir,foo一定不能是局部变量(除非调用函数等待线程完成)。参见@Gavin Lock的帖子。


根据您的评论,您需要执行以下操作...

在您的主要代码中:

1
2
3
4
5
6
7
void PassSomeStuff(struct TheStruct myStruct) {
    struct TheStruct *pStruct = malloc(sizeof(struct TheStruct));
    memcpy(pStruct, &myStruct, sizeof(struct TheStruct));

    /* Start the watchdog thread passing in the structure */
    pthread_create(/* other args */, &myWatchDogThreadFunc, pStruct); */
}

在您的看门狗线程中:

1
2
3
4
5
6
7
8
9
void *myWatchDogThreadFunc(void *pArgs) {
    struct TheStruct *pStruct = (struct TheStruct *)pArgs;

    /* use the struct */

    /* Pass Ownership to the navigation thread*/
    /* Start the navigation thread passing in the structure */
    pthread_create(/* other args */, &myNavigationThreadFunc, pStruct);
}

在您的导航线程中:

1
2
3
4
5
6
7
void *myNavigationThreadFunc(void *pArgs) {
    struct TheStruct *pStruct = (struct TheStruct *)pArgs;
    /* use the struct */

    /* cleanup */
    free(pStruct);  /* or pass it to somebody else... */
}

您不能只做:

1
2
3
void PassSomeStuff(struct TheStruct myStruct) {
    pthread_create(/* other args */, &myStruct);
}

因为myStruct将在返回时被清除...。获取地址(获取指向它的指针)不会复制该对象。

注意:

  • 只要您确定所有线程都已完成,则任何线程都可以通过调用free清理结构。
  • 所有线程(主线程,看门狗,导航)都引用该结构的同一实例(因此,如果它们更改其内容,则可能需要通过锁定保护它)。如果这不是理想的效果,那么您将需要在每个步骤中创建(malloc)该结构的新副本,以便每个线程都有自己的值副本。


如前所述,您必须传递一个指针。将void *视为未类型化的指针,因此您必须将其强制转换回线程函数中的正确类型。 (请参阅Aasmund的答案)

如forsvarir所述,您必须确保指向的结构在线程使用它之前不被破坏-最安全的方法是在堆上新建该结构并将其地址和所有权传递给线程函数。

我所说的"传递所有权"的意思是,通知该结构的函数不得删除它,而一旦完成处理,线程函数必须删除该结构。


这不是一个完整的答案,而是其他人提出的关于确保在新线程获取该结构后该结构仍然存在的警告的替代解决方案。当然,您可以使用malloc来获取它,并赋予新线程free负责。从许多方面看,这似乎是最简单,最便宜的方式(不需要同步),但是同步实际上隐藏在mallocfree内部,并且可能会稍微贵一些,特别是因为大多数面向线程的分配器(用于ptmalloc和tcmalloc的对象)例如)当释放内存的线程与分配内存的线程不同时,会产生额外的费用。

您可以使用的另一种方法是将pthread屏障放入init结构中,然后等待它:

1
2
3
pthread_barrier_init(&init_struct.barrier, 0, 2);
pthread_create(&td, 0, start_func, &init_struct);
pthread_barrier_wait(&init_struct.barrier);

并且在将结构复制到自己的自动存储中之后,让线程启动功能也调用pthread_barrier_wait(arg->barrier);