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

时间:2019-06-04 19:11:00

标签: multithreading gtk3 glib

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

我的目的是为当我单击“取消”按钮(线程B)时创建的具有结束线程A功能的线程编写函数。

我使用函数<div id="leftCol" class="edgePanel" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'left'" style="width:15%;"> <TABLE cellSpacing=1 cellPadding=0 align=left summary="This table is for design purposes and contains links in the first column only. There is a description of the link preceeding the actual link."> <TBODY> <TR> <TD vAlign=top align=left> <script>debugger;</script> <c:forEach varStatus="linkStatus" items="${sessionScope.HOMEPAGEPB.homePageValueObjList}" var="linkLoop"> <p class="plessmargin"> <c:choose > <c:when test="${linkLoop.helpType == '1660'}"> <c:set var="linkTxt" value="${linkLoop.helpExtLink}"/> <c:set var="targetTxt" value="_new"/> </c:when> <c:otherwise > <c:set var="linkTxt" value="${pageContext.request.contextPath}/${linkLoop.helpExtLink}?menuid=${linkLoop.sysFunctId}"/> <c:set var="targetTxt" value=""/> </c:otherwise> </c:choose> <span id=" <c:out value="${linkLoop.sysFunctId}"/> " class="highlight"> <a href =" <c:out value="${linkTxt}"/> " title=" <c:out escapeXml="false" value="${linkLoop.helpTxt}"/> " target=" <c:out value="${targetTxt}"/> "> <c:out value="${linkLoop.menuTxt}"/> </a> </span> </p> </c:forEach> </TD> </TR> </TBODY> </TABLE> </div>创建线程A。但是,我找不到任何类似于g_thread_create的函数来停止使用线程B的线程A。这是可能的还是无法完成的?

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

2 个答案:

答案 0 :(得分:3)

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

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

就像OznOg所说的那样,您应该将GCancellable视为一种((线程安全地)告诉您的任务应该取消的方式)。根据长期任务的编写方式,您可以在每个循环迭代中检查一次g_cancellable_is_cancelled(),也可以将g_cancellable_source_new()中的GSource添加到任务中的轮询循环中。 / p>

advice about using threads with GLib在这里也可能与此有关。

答案 1 :(得分:1)

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

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