如何从另一个线程(Glib 线程)取消一个线程?

How to cancel a thread from another thread (Glib threads)?

我正在使用 GTK 和 GLib 中的线程函数开发一个应用程序库。我有一个线程(从现在起将称为线程 A),它是在我点击某个图形 window 中的 "ok" 按钮时创建的。线程 A 开始做一些繁重的任务。另一个名为 "cancel" 的按钮可用于随时停止和完成线程 A。

我的目标是为我点击 "cancel" 按钮(线程 B)时创建的线程编写一个函数,该函数能够结束线程 A。

我用函数 g_thread_create 创建线程 A。但是我找不到任何类似于 g_thread_cancel 的函数来使用线程 B 停止线程 A。这可能还是不能完成?

非常感谢您提供的各种信息。

您可能要考虑使用 GTask 来 运行 您在线程中的任务,而不是使用 manually-created 线程。如果您使用 g_task_run_in_thread(),该操作将 运行 自动在单独的线程中进行。

GTaskGCancellable 集成,因此要取消操作,您可以在“取消”按钮的回调中调用 g_cancellable_cancel()

正如 OznOg 所说,您应该将 GCancellable 视为一种温和的方式(和 thread-safely)告诉您的任务它应该取消。根据您的 long-running 任务的编写方式,您可以检查 g_cancellable_is_cancelled() once per loop iteration, or you could add the GSource from g_cancellable_source_new() 到任务中的轮询循环。

advice about using threads with GLib 可能也与此相关。

我开发了一个代码,可以从另一个线程中取消一个线程,这两个线程都是从一个主线程创建的。根据我的测试,代码可以正常工作:

#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

但是,正如 OznOg 和 Philip Withnall 所说,这不是取消线程的正确方法。这只是一种快速的方法,在某些特定情况下可能不起作用。一个更好更安全的方法是轻轻地让线程自己停止。