2012-03-15 56 views
5

Tôi đang bắt đầu một chuỗi bằng cách sử dụng AfxBeginThread. Điều này trả về một con trỏ đến một đối tượng CWinThread mới.Ai sở hữu CWinThread sau khi được tạo bởi AfxBeginThread?

MSDN tuyên bố rằng con trỏ này là NULL và nó sẽ giải quyết mọi thứ nếu tạo chuỗi không thành công. Tuy nhiên ngay sau khi thoát khỏi chuỗi sau khi bắt đầu thường xuyên, đối tượng CWinThread vẫn tồn tại. Tôi không chắc chắn nếu tôi nên xóa các đối tượng CWinThread hoặc nếu điều này được thực hiện bởi MFC chính nó (mặc dù nó không có vẻ như vậy).

FYI không có khả năng thoát khỏi chuỗi, vì nó sẽ chạy cho đến khi ứng dụng kết thúc. Tuy nhiên kể từ khi tôi sử dụng nó là một phần của một hồ bơi thread, tôi không muốn CWinThread để treo aorund cho bao giờ hết.

Trả lời

2

Nếu chuỗi của bạn vẫn đang chạy, bạn không nên xóa nó. Một khi nó đã dừng lại, chỉ cần sử dụng toán tử delete trên con trỏ trả về bởi AfxBeginThread để giải phóng bộ nhớ được sử dụng bởi các chủ đề:

CWinThread *thread = AfxBeginThread(...); 
/* ... */ 
// now wait for it to terminate 
WaitForSingleObject(thread->m_hThread, INFINITE); 
delete thread; 

Bạn nên lưu trữ các CWinThread con trỏ đến chủ đề/ứng dụng của bạn kết thúc, do đó bạn có thể giải phóng bộ nhớ được phân bổ cho chúng. Nếu không, bạn sẽ bị rò rỉ bộ nhớ.

+4

Câu trả lời này sai. Khi kết thúc chuỗi, 'CWinThread' sẽ đóng chốt xử lý và xóa chính nó. Do đó mã này có thể gọi là 'WaitForSingleObject' trên một chốt đóng, đó là hành vi không xác định, hoặc nó có thể cố gắng xóa một đối tượng đã bị xóa. Cách tiếp cận đúng là sử dụng 'm_bAutoDelete' trên một chuỗi _suspended_, như được giải thích trong câu trả lời bởi @jla. –

4

Tôi chưa bao giờ tin tưởng CWinThread sẽ tự dọn dẹp. Tôi thường tạo chủ đề và tôi nói với MFC rằng tôi sẽ làm sạch, đặc biệt khi chương trình đóng:

CWinThread *thread = AfxBeginThread(...); 
thread->m_bAutoDelete = FALSE; 

Tuy nhiên, bạn sẽ phải lưu con trỏ luồng nếu không bạn sẽ bị rò rỉ bộ nhớ.

+0

cảm ơn bạn, tôi vừa phát hiện ra về thành viên m_bAutoDelete và làm như bạn và @fontanini đề xuất. +1 – Alex

+3

Câu trả lời này sai. Vào lúc mã này cố gắng thiết lập 'm_bAutoDelete', đối tượng' CWinThread' có thể đã tự xóa nó. Xem câu trả lời của @jla về cách sử dụng kỹ thuật này một cách chính xác. –

+0

Tôi không đồng ý rằng câu trả lời là sai. Chìa khóa cho câu trả lời là m_bAutoDelete, và tham số trong mẫu được "..." bỏ qua cho ngắn gọn. Nó cũng bắt buộc CREATE_SUSPENDED, nếu không, bình luận của bạn là chính xác. Tôi đồng ý rằng câu trả lời của @ jila hoàn chỉnh hơn. –

7

Trách nhiệm làm sạch đối tượng CWinThread phụ thuộc vào giá trị m_bAutoDelete. Mặc định là xóa chính nó. Đối với lửa và quên các chủ đề chạy ngắn, điều này là tốt. Nó sẽ tự làm sạch.

Nếu chuỗi của bạn chạy dài và cần được thông báo đã đến lúc thoát hoặc tương tác với nhau, bạn sẽ muốn điều khiển CWinThread vẫn hợp lệ và không trỏ đến đối tượng tự xóa.

Nếu bạn đặt m_bAutoDelete thành FALSE, bạn có trách nhiệm xóa nó. Để chơi nó an toàn với con trỏ trả về, bạn nên tạo tạm ngưng và đặt nó thành FALSE trước khi tiếp tục theo đề xuất của Joseph Newcomer trong bài viết Using Worker Threads của mình.

thread = AfxBeginThread(proc, this, 
         THREAD_PRIORITY_NORMAL, // default: use it 
         0,  // default stack size 
         CREATE_SUSPENDED); // let us set auto delete 
    if(thread) { // protect against that rare NULL return 
     thread->m_bAutoDelete = FALSE; 
     thread->ResumeThread(); 
    } 
+2

Đây là câu trả lời đúng duy nhất. Hai câu trả lời còn lại là sai và có thể gây ra hành vi không xác định. –

+0

Nếu bạn có một chủ đề GUI với m_bAutoDelete = TRUE và bạn quan sát thấy luồng không thoát ra mặc dù người dùng nhấp vào nút "Đóng" của cửa sổ chính, có thể cần phải gọi PostQuitMessage() trong PostNcDestroy(). – Elmue

+1

Cũng lưu ý rằng nếu bạn đang tự dọn dẹp sau chỉ luồng (m_bAutoDelete = FALSE), bạn sẽ vẫn muốn đợi chuỗi thoát trước khi xóa đối tượng – Luis

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