0

我正在尝试使用 pthreads 在 C 中模拟回调机制。我的代码如下:

#include <stdio.h>
#include <pthread.h>

struct fopen_struct {
  char *filename;
  char *mode;
  void *(*callback) (FILE *);
};

void *fopen_callback(FILE *);
void fopen_t(void *(*callback)(FILE *), const char *, const char *);
void *__fopen_t__(void *);

void fopen_t(void *(*callback)(FILE *), const char *filename, const char *mode) {
  struct fopen_struct args;
  args.filename = filename;
  args.mode = mode;
  args.callback = callback;
  pthread_t thread;
  pthread_create(&thread, NULL, &__fopen_t__, &args);
}

void *__fopen_t__(void *ptr) {
  struct fopen_struct *args = (struct fopen_struct *)ptr;
  FILE *result = fopen(args -> filename, args -> mode);
  args -> callback(result);
}

int main() {
  fopen_t(&fopen_callback, "test.txt", "r");
}

void *fopen_callback(FILE *stream) {
  if (stream != NULL)
    printf("Opened file successfully\n");
  else
    printf("Error\n");
}

这会编译,但在执行时,它会在屏幕上没有错误或消息的情况下完成。我错过了什么?

4

2 回答 2

3

您的main线程在完成之前退出__fopen_t__。因此,要么分离该线程(fopen_t) usingpthread_detach并做其他有用的事情,要么等待__fopen_t__using完成pthread_join

使用时pthread_join,您fopen_t可能看起来像,

void fopen_t(void *(*callback)(FILE *), const char *filename, const char *mode)
{
    struct fopen_struct args;
    args.filename = filename;
    args.mode = mode;
    args.callback = callback;
    pthread_t thread;
    pthread_create(&thread, NULL, &__fopen_t__, &args);
    pthread_join( thread, NULL );   // Waiting till the new thread completes
}

有关详细信息,请参阅手册页pthread_detachpthread_join


根据 R.. 的评论,为了更合乎逻辑,下面给出了动态分配的代码。

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

struct fopen_struct {
    char *filename;
    char *mode;
    void *(*callback) (FILE *);
};

void *fopen_callback(FILE *);
pthread_t* fopen_t(void *(*callback)(FILE *), const char *, const char *);
void *__fopen_t__(void *);

// returns pthread_t* to be freed by caller
pthread_t* fopen_t(void *(*callback)(FILE *), const char *filename, const char *mode)
{

    struct fopen_struct *args = calloc( 1, sizeof(  struct fopen_struct ) );
    args->filename = filename;
    args->mode = mode;
    args->callback = callback;

    pthread_t *thread = calloc( 1, sizeof( pthread_t ) );   // Need error checks
    pthread_create( thread, NULL, &__fopen_t__, args);
    //pthread_join( thread, NULL ); // `thread` is returned to caller

    return thread;
}

// takes `struct fopen_struct*` as argument and will be freed
void *__fopen_t__(void *ptr) {
    struct fopen_struct *args = (struct fopen_struct *)ptr;
    FILE *result = fopen(args -> filename, args -> mode);
    args -> callback(result);

    free( args ); args = NULL;
    return NULL;
}

int main() {
    pthread_t *th_id = NULL;

    th_id = fopen_t(&fopen_callback, "test.txt", "r");      // Need error checks
    pthread_join( *th_id, NULL );  // Wait till the __fopen_t__ thread finishes
    free( th_id ); th_id = NULL;

    return 0;
}
于 2013-06-19T08:17:48.520 回答
0

在主程序的底部添加sleep()。也许你的程序在得到结果之前就完成了。

附加评论

这是注意到此错误的最简单方法,但不是正确的方法。:)

于 2013-06-19T08:14:54.770 回答