【问题标题】:How to cancel a thread from another thread (Glib threads)?如何从另一个线程(Glib 线程)中取消一个线程?
【发布时间】:2019-06-04 19:11:00
【问题描述】:

我正在使用 GTK 和 GLib 中的线程函数开发一个应用程序库。我有一个线程(从现在起将称为线程 A),当我在某个图形窗口中单击“确定”按钮时创建该线程。线程 A 开始执行一些繁重的任务。另一个名为“取消”的按钮可用于随时停止和结束线程 A。

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

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

非常感谢您提供的任何信息。

【问题讨论】:

  • 取消线程恕我直言是一种不好的做法,特别是因为取消点通常是众所周知且有限的。这造成了代码似乎有效但主要希望有效的情况。如果你想停止一个线程,你应该能够要求它轻轻地停止它应该能够做的事情。

标签: multithreading gtk3 glib


【解决方案1】:

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

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

正如 OznOg 所说,您应该将 GCancellable 视为一种温和(且线程安全)告诉您的任务应该取消的方式。根据您的长时间运行任务的编写方式,您可以在每次循环迭代时检查一次g_cancellable_is_cancelled(),或者您可以将来自g_cancellable_source_new()GSource 添加到任务中的轮询循环中。

advice about using threads with GLib 在这里可能也很重要。

【讨论】:

    【解决方案2】:

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

    #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 所说,这不是取消线程的正确方法。这只是一种快速的方法,在某些特定情况下可能不起作用。更好更安全的方法是轻轻地让线程自行停止。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-16
      • 2017-12-19
      • 1970-01-01
      • 1970-01-01
      • 2015-08-29
      相关资源
      最近更新 更多