Как отменить тему из другой темы (Glib темы)? - PullRequest
1 голос
/ 04 июня 2019

Я занимаюсь разработкой библиотеки приложений с использованием GTK и функций для потоков в GLib.У меня есть поток (теперь он будет называться потоком A), который создается, когда я нажимаю кнопку «ОК» в определенном графическом окне.Поток A начинает выполнять тяжелые задачи.Другая кнопка с именем «отмена» доступна для остановки и завершения потока А. в любой момент.

Моя цель состоит в том, чтобы закодировать функцию для потока, созданного, когда я нажимаю кнопку «отменить» (поток В), которая имеетвозможность завершения потока A.

Я создаю поток A с функцией g_thread_create.Однако я не могу найти какую-либо функцию, аналогичную g_thread_cancel, чтобы остановить поток A с помощью потока B. Это возможно или не может быть сделано?

Большое спасибо за предоставленную информацию.

Ответы [ 2 ]

3 голосов
/ 04 июня 2019

Возможно, вы захотите использовать GTask для запуска задачи в потоке, а не в ручном создании потока.Если вы используете g_task_run_in_thread(), операция будет выполняться в отдельном потоке автоматически.

GTask интегрируется с GCancellable, поэтому для отмены операцииВы бы позвонили g_cancellable_cancel() в обратном вызове с помощью кнопки «Отмена».

Как говорит OznOg, вы должны относиться к GCancellable как к способу аккуратного (и безопасного для потока) сообщения вашей задаче, что он долженотменить.В зависимости от того, как написана ваша долгосрочная задача, вы можете либо проверить g_cancellable_is_cancelled() один раз за итерацию цикла, либо добавить GSource из g_cancellable_source_new() в опросцикл в вашей задаче.

Совет по использованию потоков с GLib , вероятно, также уместен здесь.

1 голос
/ 05 июня 2019

Я разработал код, который может отменить поток из другого, оба они созданы из основного.Код работает корректно в соответствии с моими тестами:

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

    /* these variables are references to the first and second threads */
    pthread_t inc_x_thread, inc_y_thread;

/* this function is run by the first thread */
void *inc_x(void *x_void_ptr)
{

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

    /* increment x to 100 */
    int *x_ptr = (int *)x_void_ptr;



    while(++(*x_ptr) < 100000000);


    printf("x increment finished\n");

    /* the function must return something - NULL will do */
    return NULL;
}

/* this function is run by the second thread */
void *inc_y(void *x_void_ptr)
{

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

    /* increment y to 100 */
    int *x_ptr = (int *)x_void_ptr;

    pthread_cancel(inc_x_thread);

    while(++(*x_ptr) < 100);

    printf("y increment finished\n");

    return NULL;
}

/* this is the main thread */
int main()
{

    int x = 0, y = 0;
    void *res;

    /* show the initial values of x and y */
    printf("x: %d, y: %d\n", x, y);

    /* create a first thread */
    if(pthread_create(&inc_x_thread, NULL, inc_x, &x)) {
        fprintf(stderr, "Error creating thread\n");
        return 1;
    }

    /* create a second thread */
    if(pthread_create(&inc_y_thread, NULL, inc_y, &y)) {
        fprintf(stderr, "Error creating thread\n");
        return 1;
    }

    /* wait for the first thread to finish */
    if(pthread_join(inc_x_thread, &res)) {
        fprintf(stderr, "Error joining thread\n");
        return 2;
    }

           if (res == PTHREAD_CANCELED)
               printf(" thread was canceled\n");
           else
               printf(" thread wasn't canceled\n");

    /* wait for the second thread to finish */
    if(pthread_join(inc_y_thread, &res)) {
        fprintf(stderr, "Error joining thread\n");
        return 2;
    }

           if (res == PTHREAD_CANCELED)
               printf(" thread was canceled\n");
           else
               printf(" thread wasn't canceled\n");

    /* show the results*/
    printf("x: %d, y: %d\n", x, y);

    return 0;
}

Вы можете скомпилировать код, используя: gcc example.c -lpthread

Однако, как сказали ОзнОг и Филипп Сналл, это не правильноспособ отменить тему.Это только быстрый способ сделать это, который может не сработать в некоторых конкретных ситуациях.Лучший и более безопасный способ - осторожно попросить нить остановиться.

...