Làm thế nào tôi có thể chờ đợi để chấm dứt thread?

Giả sử từ chủ đề chính chúng tôi tạo ra một chủ đề khác. Đó là suppoused để làm một số công việc và kết thúc. Đôi khi chủ đề chính muốn biết khi nào thread đã thoát. Thông thường họ đề nghị sử dụng một cái gì đó như thế này:

Xử lý hThread;
/ *
Tạo chủ đề,
thread làm một số công việc ...
Nó có thể thoát ra khỏi chính nó hoặc chúng tôi gửi tin nhắn đến thread để thoát.
* /
chuyển đổi (WaitForSingleObject (hThread, nTimeOut_IfAny)) {
	trường hợp WAIT_OBJECT_0:
		/ / Chủ đề đã đi, phản ứng bằng cách nào đó:
		fThreadFinished = true;
		phá vỡ;
	trường hợp WAIT_TIMEOUT:
		// Hết thời gian chờ, chủ đề vẫn đang chạy
		fThreadFinished = sai;
		phá vỡ;
	mặc định :
		// Có gì đó không đúng...
};

Lưu ý rằng việc chờ đợi này được thực hiện trong chủ đề chính, có thể có một số thông báo xuất hiện và từ chủ đề con quá. Nhưng chúng tôi không bơm thông báo này – điều đó rất tồi tệ. Điều này làm cho ứng dụng bị đông lạnh (không có phản hồi bằng bàn phím, không có bản cập nhật GUI). Nếu timeout quá dài và thread con sử dụng SendMessage()chức năng để gửi tin nhắn đến thread chính – bế tắc xảy ra. Để tránh điều này chúng ta cần phải chờ đợi cho thread và vẫn xử lý hàng đợi tin nhắn. Một khi tôi giải quyết nó theo cách này:

trong khi (true) {
 MSG msg;
 trong khi (PeekMessage (& msg ;, NULL, 0, 0, PM_REMOVE))
   DispatchMessage (& msg;);
   Kết quả DWORD = MsgWaitForMultipleObjects (1, & hThread ;, FALSE, nTimeOut, QS_ALLINPUT);
   if (result! = (WAIT_OBJECT_0 + 1))
      phá vỡ; / / Chủ đề là đã thoát
}

Điều này đã giúp. Sau đó tôi đã được khuyên để xem cách ATL chức năng AtlWaitWithMessageLoop()được thực hiện. Tôi thấy phương pháp của tôi gần đúng. Đây là một đoạn mã của hàm đó (ATLBASE.h):

BOOL AtlWaitWithMessageLoop (HANDLE hEvent)
{
  DWORD dwRet;
  MSG msg;

  trong khi (1)
  {
    dwRet = MsgWaitForMultipleObjects (1, & hEvent ;, FALSE, INFINITE, QS_ALLINPUT);

    if (dwRet == WAIT_OBJECT_0)
       trả về TRUE; // Sự kiện được báo hiệu

    if (dwRet! = WAIT_OBJECT_0 + 1)
       phá vỡ; // Có chuyện gì khác đã xảy ra

    // Có một hoặc nhiều thông báo cửa sổ khả dụng. Gửi chúng
    trong khi (PeekMessage (& msg, NULL, NULL, NULL, PM_REMOVE))
    {
      TranslateMessage (& msg;);
      DispatchMessage (& msg;);
      if (WaitForSingleObject (hEvent, 0) == WAIT_OBJECT_0)
         trả về TRUE; // Sự kiện hiện báo hiệu.
    }
  }
  trả về FALSE;
}

nơi đầu vào hEventlà xử lý chủ đề. Chức năng này sẽ không trở lại cho đến khi sợi còn sống nhưng hàng đợi tin nhắn của thread gọi (thường là một chính) sẽ được bơm.

Là một tác dụng phụ tôi đã sửa đổi các chức năng để sử dụng nó thay vì Sleep()chức năng dummy API . Bạn có thể chờ đợi cho chủ đề bây giờ có hoặc không có thời gian chờ hoặc chỉ cần chờ đợi một thời gian nhất định mà không khóa hàng đợi tin nhắn. Cuộc gọi: waitWithMessageLoop(0, 2000)waitWithMessageLoop(hThread),waitWithMessageLoop(hThread, 5000)

BOOL waitWithMessageLoop (HANDLE hEvent = 0, DWORD dwTimeout = INFINITE);

BOOL chờ đợiMessageLoop (HANDLE hEvent, DWORD dwTimeout)
{
  DWORD dwRet;
  MSG msg;
  hEvent = hEvent? hEvent: CreateEvent (NULL, FALSE, FALSE, NULL);
  
  trong khi (đúng)
  {
    dwRet = MsgWaitForMultipleObjects (1, & hEvent ;, FALSE, dwTimeout, QS_ALLINPUT);
    if (dwRet == WAIT_OBJECT_0)
       trả về TRUE;
    if (dwRet! = WAIT_OBJECT_0 + 1)
       phá vỡ;
    trong khi (PeekMessage (& msg, NULL, NULL, NULL, PM_REMOVE))
    {
      TranslateMessage (& msg;);
      DispatchMessage (& msg;);
      if (WaitForSingleObject (hEvent, 0) == WAIT_OBJECT_0)
         trả về TRUE;
    }
  }
  trả về FALSE;
}

Leave a Reply

Your email address will not be published. Required fields are marked *