前面我们在开发的sort
函数用到了回调函数。因为排序示例没有用到多线程,有些程序员认为这不是回调函数。大家普遍认可的定义是如果一个线程的事件导致另一个线程的函数调用,就称为回调。将回调函数的指针传递给线程,而函数的某个事件会引发对回调函数的调用,这种方法在GUI应用程序中处理用户线程事件很有用。
我们会用一个计算阶乘的函数说明这种方法,这个函数会在计算完阶乘后回调第二个函数。关于阶乘的信息封装在FactorialData
结构体中,并在两个函数之间传递。这个结构体和阶乘函数如下所示,数据包括阶乘数、结果和回调用的函数指针。factorial
函数用这些数据计算阶乘,把结果保存到result
字段,调用回调函数,然后结束线程:
typedef struct _factorialData {
int number;
int result;
void (*callBack)(struct _factorialData*);
} FactorialData;
void factorial(void *args) {
FactorialData *factorialData = (FactorialData*) args;
void (*callBack)(FactorialData*); // 函数原型
int number = factorialData->number;
callBack = factorialData->callBack;
int num = 1;
for(int i = 1; i<=number; i++) {
num *= i;
}
factorialData->result = num;
callBack(factorialData);
pthread_exit(NULL);
}
我们在startThread
函数中创建一个线程,如下所示。这个线程会执行factorial
函数,给它传递阶乘数据:
void startThread(FactorialData *data) {
pthread_t thread_id;
int thread = pthread_create(&thread_id, NULL, factorial, (void *) data);
}
回调函数只是简单地打印阶乘结果:
void callBackFunction(FactorialData *factorialData) {
printf("Factorial is %d\n", factorialData->result);
}
初始化阶乘数据和调用startThread
函数的代码如下所示。Sleep
函数为所有线程正常结束提供足够的时间:
FactorialData *data =
(FactorialData*) malloc(sizeof(FactorialData));
if(!data) {
printf("Failed to allocate memory\n");
return;
}
data->number = 5;
data->callBack = callBackFunction;
startThread(data);
Sleep(2000);
执行代码后输出如下:
Factorial is 120
程序也可以执行其他任务而不休眠,它无需等待线程完成。