Асинхронный вызов функции для C++

Мне нужна подсказка, как реализовать асинхронные вызовы функции в C/C++ (или названия ПЛАТФОРМ/ВЫЗОВОВ API для окон и/или Linux)

Вариант использования следует: родительский поток вызывает функцию. Функция создает дочерний поток и возврат, таким образом, вызов не блокируется, и родительский поток может продолжить делать некоторое задание.

Например, pthread_join для получения результата не подходит, таким образом, результат должен быть сохранен где-нибудь в "куче", и родитель должен быть уведомлен о. То, что я хочу, является чем-то как функция обратного вызова в родительском потоке, который был бы выполнен после того, как дочерний поток готов с заданием.

Это удивительно, но я не могу найти единственный пример в Google.

Спасибо за справку

6
задан iddqd 2 August 2010 в 16:35
поделиться

8 ответов

Я предлагаю вам проверить http://www.threadingbuildingblocks.org/.

Класс Task (http://cache-www.intel.com/cd/00/00/30/11/301114_301114.pdf#page=95) может быть отправной точкой.

4
ответ дан 8 December 2019 в 05:19
поделиться

Используйте фреймворк Qt и классы Thread или фреймворк Qt Concurrency.

Подключитесь к сигналу QThread::finished() или QFutureWatcher::finished(), чтобы получить уведомление о завершении работы.

0
ответ дан 8 December 2019 в 05:19
поделиться

Используйте boost :: thread как стандартное кроссплатформенное решение. Если вам нужно что-то более сложное, есть блоки Intel Thread Building Blocks.

1
ответ дан 8 December 2019 в 05:19
поделиться

Boost.Thread

Я считаю, что это хорошо работает. Разверните вызов функции как новый поток и просто не пытайтесь присоединиться к нему. Я думаю, он все равно позаботится об этом, когда закончится.

Вы можете настроить его так, чтобы потомок отправлял сигнал родителю, когда он заканчивает использование Boost.Signals . Этот сигнал будет связан с функцией обратного вызова родителя.

3
ответ дан 8 December 2019 в 05:19
поделиться

Вам нужно будет настроить какую-то инфраструктуру, чтобы уведомить звонящего о том, что работа выполнена. Это можно сделать с помощью типа шаблона Observer. Также можно использовать инфраструктуру типа сообщений.

Реальный вопрос заключается в том, что ваш родитель собирается делать, пока он ждет. Вы хотите, чтобы он опрашивал результаты? Или получить уведомление?

0
ответ дан 8 December 2019 в 05:19
поделиться

C ++ 0x предоставляет для этого std :: async . Вот существующая реализация , обсуждение и Википедия .

8
ответ дан 8 December 2019 в 05:19
поделиться

Вместо того, чтобы использовать разные фреймворки и отметить, что вы упомянули 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. Если вас беспокоит переносимость или соответствие требованиям, приведенное выше решение следует пересмотреть.

7
ответ дан 8 December 2019 в 05:19
поделиться

В вашем ответе Старки я вижу, что основной поток - это поток пользовательского интерфейса.

Я использовал несколько различных наборов инструментов с графическим интерфейсом, и все они позволяют отправлять сообщения из разных цепочек. Итак, пусть рабочий поток отправит сообщение графического интерфейса, когда оно будет завершено, обработчик затем запустится в основном потоке.

В Windows используйте PostMessage .

В Linux используйте XtAppAddSignal и XtNoticeSignal

0
ответ дан 8 December 2019 в 05:19
поделиться