功能描述:最近写了一个字符串搜索程序,搜索结果用线程(调用AddString)输出到UI(一个CListBox的窗口).
问题描述:当遇到输出结果非常多(比如几十万条)的情况下,用户关闭程序后线程依然会执行很久(当然这种执行是没有必要的).而且线程中有delete的释放内存操作,如果异常中止就会导致内存泄漏。目前我的一个想法是在主线程退出时调用PostThreadMessage,给线程发送消息,线程接收到消息后就停止当前的输出操作,释放堆内存后退出。但我没用过这个API,不大确定它是否能行得通。现在请教一下各位高手有没有一个妥善的方法让线程在主程序关闭后安全且快速地退出。PostThreadMessage这个方案是否是可行的呢?希望大家能给点意见。谢谢!

解决方案 »

  1.   

    主要是要看你调用AddString的线程是怎么写的
      

  2.   

    要看你的框架和线程是怎么设计的。如果是UI线程有消息循环,可以给它发消息,或者给它的主窗口发消息;工作者线程需要自写消息循环,才能接收处理消息,如果线程函数是一个循环,只需用全局变量就可以通知它终止。怎么感觉设计得不是很合理呢?为什么不用线程搜索、主线程来更新界面?搜索结果又是怎么告诉线程的?还有当输出结果非常多(比如几十万条)时,用CListBox控件行吗?会死掉吧?
      

  3.   

    工作者线程如果调用GetMessage是会分配消息队列的
      

  4.   

    就一个循环语句遍历vector,调用AddString把搜索结果输出.
      

  5.   

    您提到"线程搜索,主线程更新界面"的设计已经实现.我这个问题是搜索结果非常多的一种极限情况:也就是结果有几十万条时,用主线程更新界面必然导致整个程序卡死,因此,我把更新界面的操作也挪到了线程中进行.但这个线程的终止需要是可控的,程序关闭时,不管它工作与否,必须将其终止.CListBox暂时还没产生这类异常,当然这不是关注点.如果我在线程每次调用AddString之前都GetMessage一下,看是否收到一个终止的信号,再进行相应的处理,你看是否可行?
      

  6.   

    "每次调用AddString之前都GetMessage一下,看是否收到一个终止的信号,再进行相应的处理,你看是否可行?"
    应该 可行。
      

  7.   


    也就是说你只是开一个工作线程,在里面调用AddString,但这个函数相当于给主线程的窗口发送控件消息,实际上还是在主线程里运行!最好是给主线程窗口Post一个自定义消息,让主线程来更新界面。使用一个全局变量
    long volatile g_lExit = 0;启动时置0,在程序退出前将其值置为1通知线程终止,然后调用WaitForSingleObject函数等待线程句柄。线程函数里每次循环都检测它声明为volatile型可以避免编译器对其优化致使不能读取新值
      

  8.   

    我每建立一个线程 ,都会传递一个结构体,里面至少包含一个 stoppending 事件句柄。
      

  9.   

    "如果我在线程每次调用AddString之前都GetMessage一下,看是否收到一个终止的信号,再进行相应的处理,你看是否可行?"----可以的。不过要用PeekMessage而不是GetMessage。
    主界面响应仍然可能不会很及时,会延迟
      

  10.   

      感谢大家回复了这么多,我总结起来,大致有两个方法:
    1是设置若干共享变量用于表示主线程和工作线程的状态,主线程和工作线程就通过查看这些共享变量进行同步。主线程直到成功通知工作线程结束后才会退出。
    2是主线程在退出时向工作线程post一条信息后立即退出。工作线程在自己的循环体内调用获取消息的API,收到对应消息后主动退出。但由于我目前还没实现它们,不知道主程序退出后,线程的消息队列是否还会被系统继续保留,这方面欢迎高手们赐教。
      再次谢谢大家!
      

  11.   

    你说的第2种方法:主线程在退出时向工作线程post一条信息后立即退出
    不是一个好方法,这可能和直接退出没什么区别,因为如果主线程退出时进程也终止了,工作线程将被强迫终止,这样它来不及做应做的清理工作,C++类对象将得不到析构,...
    主线程要调用等待函数等到线程句柄后再退出,这样才能确保工作线程先正常结束