2009-02-26 37 views
10

tôi đẻ trứng một sợi sử dụng AfxBeginThread mà chỉ là vô hạn trong khi vòng lặp:Làm thế nào để tiêu diệt một Chủ đề MFC?

UINT CMyClass::ThreadProc(LPVOID param) 
{ 
    while (TRUE) 
    { 
     // do stuff 
    } 
    return 1; 
} 

Làm thế nào để giết chết chủ đề này trong destructor lớp học của tôi?

Tôi nghĩ rằng một cái gì đó giống như

UINT CMyClass::ThreadProc(LPVOID param) 
{ 
    while (m_bKillThread) 
    { 
     // do stuff 
    } 
    return 1; 
} 

và sau đó thiết lập m_bKillThread-FALSE trong destructor. Nhưng tôi vẫn cần phải chờ trong destructor cho đến khi thread đã chết.

Trả lời

19

Tích cực tiêu diệt các chủ đề:

Sử dụng các giá trị trở lại của AfxBeginThread (CWinThread*) để có được xử lý chủ đề (m_hThread) sau đó vượt qua có thể xử lý với API TerminateThread Win32. Đây không phải là một cách an toàn để chấm dứt chủ đề mặc dù, vì vậy hãy đọc tiếp.

chờ cho thread để kết thúc:

Sử dụng giá trị trả về của AfxBeginThread (CWinThread*) để có được những thành viên m_hThread, sau đó sử dụng WaitForSingleObject(p->m_hThread, INFINITE); Nếu hàm này trả WAIT_OBJECT_0, sau đó các chủ đề kết thúc. Thay vì INFINITE bạn cũng có thể đặt số mili giây để chờ trước khi hết thời gian chờ. Trong trường hợp này, WAIT_TIMEOUT sẽ được trả lại.

tín hiệu vào chủ đề của bạn mà nó nên kết thúc:

Trước khi làm WaitForSingleObject chỉ cần thiết lập một số loại cờ mà thread nên thoát. Sau đó, trong vòng lặp chính của chủ đề bạn sẽ kiểm tra giá trị bool đó và phá vỡ vòng lặp vô hạn. Trong destructor của bạn, bạn sẽ thiết lập cờ này sau đó làm một WaitForSingleObject.

cách Thậm chí tốt hơn:

Nếu bạn cần kiểm soát nhiều hơn bạn có thể sử dụng giống như boost conditions.

1

Bạn phải chờ, cho đến khi chuỗi hoạt động.

if(WaitForSingleObject(thread_handle, INFINITE) == WAIT_OBJECT_0) 
    ;//all right 
else 
    ;//report error 

hãy cẩn thận bằng chức năng TerminateThread, điều này rất nguy hiểm.

4

BTW, Về TerminateThread(), hãy sử dụng theo cách này.

DWORD exit_code= NULL; 
if (thread != NULL) 
{ 
    GetExitCodeThread(thread->m_hThread, &exit_code); 
    if(exit_code == STILL_ACTIVE) 
    { 
     ::TerminateThread(thread->m_hThread, 0); 
     CloseHandle(thread->m_hThread); 
    } 
    thread->m_hThread = NULL; 
    thread = NULL; 
} 
1

Trước tiên, bạn phải bắt đầu thread trong một cách rất MFC không xóa các đối tượng thread khi nó finished, các thiết lập mặc định cho MFC sợi là xóa bản thân, do đó bạn muốn chuyển mà đi.

m_thread = AfxBeginThread(ThreadProc, this, THREAD_PRIORITY_NORMAL ,CREATE_SUSPENDED); 
    m_thread->m_bAutoDelete = FALSE; 
    m_thread->ResumeThread(); 

Bây giờ trong chuỗi, bạn muốn có một cơ chế mà chuỗi người gọi có thể gửi tín hiệu kết thúc. Có nhiều cách, một là WaitForSingleObject để kiểm tra trạng thái của tín hiệu hoặc cách khác là chỉ cần gửi chủ đề này một tin nhắn để tự kết thúc. Đây là kết thúc duyên dáng thay vì giết chết nó.

Trong khi chủ đề này tự kết thúc (= thoát khỏi hàm chuỗi, dọn dẹp), bạn có thể đợi chủ đề chính trên đó kết thúc trước khi thoát.

 int wait = 2000 // seconds (I am waiting for 2 seconds for worker to finish) 
    int dwRes = WaitForSingleObject(m_thread->m_hThread, wait); 
    switch (dwRes) 
    { 
    case WAIT_OBJECT_0: 
     TRACE(_T("worker thread just finished")); break; 
    case WAIT_TIMEOUT: 
     TRACE(_T("timed out, worker thread is still busy")); break; 
    } 

Lưu ý thiết lập m_bAutoDelete = FALSE ở trên làm cho chúng tôi có thể vẫn có tay cầm hợp lệ khi ren kết thúc để chúng tôi có thể đợi. Điều cuối cùng bạn muốn làm bây giờ là xóa đối tượng CWinThread để giải phóng bộ nhớ của nó (vì chúng ta đã chịu trách nhiệm thực hiện điều đó).

Các vấn đề liên quan