Мне нужна подсказка, как реализовать асинхронные вызовы функции в C/C++ (или названия ПЛАТФОРМ/ВЫЗОВОВ API для окон и/или Linux)
Вариант использования следует: родительский поток вызывает функцию. Функция создает дочерний поток и возврат, таким образом, вызов не блокируется, и родительский поток может продолжить делать некоторое задание.
Например, pthread_join для получения результата не подходит, таким образом, результат должен быть сохранен где-нибудь в "куче", и родитель должен быть уведомлен о. То, что я хочу, является чем-то как функция обратного вызова в родительском потоке, который был бы выполнен после того, как дочерний поток готов с заданием.
Это удивительно, но я не могу найти единственный пример в Google.
Спасибо за справку
Я предлагаю вам проверить http://www.threadingbuildingblocks.org/.
Класс Task (http://cache-www.intel.com/cd/00/00/30/11/301114_301114.pdf#page=95) может быть отправной точкой.
Используйте фреймворк Qt и классы Thread или фреймворк Qt Concurrency.
Подключитесь к сигналу QThread::finished() или QFutureWatcher::finished(), чтобы получить уведомление о завершении работы.
Используйте boost :: thread как стандартное кроссплатформенное решение. Если вам нужно что-то более сложное, есть блоки Intel Thread Building Blocks.
Я считаю, что это хорошо работает. Разверните вызов функции как новый поток и просто не пытайтесь присоединиться к нему. Я думаю, он все равно позаботится об этом, когда закончится.
Вы можете настроить его так, чтобы потомок отправлял сигнал родителю, когда он заканчивает использование Boost.Signals . Этот сигнал будет связан с функцией обратного вызова родителя.
Вам нужно будет настроить какую-то инфраструктуру, чтобы уведомить звонящего о том, что работа выполнена. Это можно сделать с помощью типа шаблона Observer. Также можно использовать инфраструктуру типа сообщений.
Реальный вопрос заключается в том, что ваш родитель собирается делать, пока он ждет. Вы хотите, чтобы он опрашивал результаты? Или получить уведомление?
C ++ 0x предоставляет для этого std :: async
. Вот существующая реализация , обсуждение и Википедия .
Вместо того, чтобы использовать разные фреймворки и отметить, что вы упомянули pthread_join ()
в своем вопросе, вы все равно можете достичь желаемого эффекта с помощью POSIX C. Для этого вы можете использовать сигналы для подтверждения поток завершения параллельной задачи. В этом методе вы устанавливаете обработчик сигнала для определяемого пользователем сигнала (например, SIGUSR1
), создаете набор рабочих потоков с различными задачами и позволяете им сигнализировать родителю о завершении.
Следующая программа иллюстрирует эту попытку. В этом примере я использую SIGUSR1
, чтобы сообщить родительскому потоку о завершении некоторой обработки. Родительский поток занят выполнением некоторого ввода-вывода, пока его не прервет дочерний поток. Обратите внимание, что для ясности не было помещено никакого кода обработки ошибок.
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/* Variable to hold the value of some calculation. */
int value = 0;
/* Variable used by the parent thread to inform itself of task completion. */
volatile sig_atomic_t value_received = 0;
/* Signal handler to handle the SIGUSR1 signal (the signal used to acknowledge the parent of task completion). */
void handler(int signum) {
value_received = 1;
}
/* Working thread routine. First parameter is a pthread_t (cast to void*) identifying the parent. */
void *thread(void *parent) {
/* Do something lengthy here, such as a long calculation. */
value = 1;
sleep(5); /* Simulate lengthy operation. */
/* After processing, inform the parent thread that we have ended. */
pthread_kill((pthread_t)parent, SIGUSR1);
return NULL;
}
int main(void) {
struct sigaction action;
pthread_t child;
/* Install signal handler to receive the child thread notification. */
action.sa_handler = handler;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
sigaction(SIGUSR1, &action, NULL);
/* Create child thread that will perform some task. */
pthread_create(&child, NULL, thread, (void*)pthread_self());
/* Detach thread from execution. No need to join the thread later. */
pthread_detach(child);
/* Do some other processing while the ongoing task is running in parallel. */
while (!value_received) {
char buffer[0x100];
/* Echo some input until something happens. */
if (!fgets(buffer, sizeof buffer, stdin))
break;
printf("You typed: %s", buffer);
}
/* Something happened (signal received or EOF in stdin). In the latter, just sleep a little while. */
if (feof(stdin))
while (!value_received)
sleep(1);
/* At this point, child thread has already ended the execution. */
printf("Value received: %i\n", value);
return EXIT_SUCCESS;
}
В этом примере используется реализация сигналов LinuxThreads, которая сильно отличается от того, что определяет POSIX. Если вас беспокоит переносимость или соответствие требованиям, приведенное выше решение следует пересмотреть.
В вашем ответе Старки я вижу, что основной поток - это поток пользовательского интерфейса.
Я использовал несколько различных наборов инструментов с графическим интерфейсом, и все они позволяют отправлять сообщения из разных цепочек. Итак, пусть рабочий поток отправит сообщение графического интерфейса, когда оно будет завершено, обработчик затем запустится в основном потоке.
В Windows используйте PostMessage
.
В Linux используйте XtAppAddSignal
и XtNoticeSignal