1. 程式人生 > >在主執行緒中慎用WaitForSingleObject (WaitForMultipleObjects) --代替方法:MsgWaitForMultipleObjects

在主執行緒中慎用WaitForSingleObject (WaitForMultipleObjects) --代替方法:MsgWaitForMultipleObjects

下面的程式碼我除錯了將近一個星期,你能夠看出什麼地方出了問題嗎?

執行緒函式:

 DWORD WINAPI ThreadProc(
    
while ( ! bTerminate)
    
 {
        
//  從一個連結串列中讀取資訊並且插入到CListCtrl中
        
//  CListCtrl的控制代碼是通過執行緒引數傳遞進來的  for (;;)
       
 {
           ReadInfoFromList();
           InsertToCListCtrl();
        }
 

    }

}
  主執行緒中使用CreateThread啟動執行緒。

當想終止子執行緒時,在主執行緒中:
bTerminate = TRUE;
WaitForSingleObject(threadHandle, INFINITE);
可是,以執行到WaitForSingleObject,子執行緒就Crash了。

為什麼呢?

問題原因:
後來我終於在InsertItem的反彙編中發現瞭如下的程式碼
call dword ptr [
[email protected]
(7C141B54h)]
可見,InsertItem是必須藉助訊息迴圈來完成任務的。如果我們在主執行緒中WaitForSingleObject了,必然導致主執行緒阻塞,也就導致了訊息迴圈的阻塞,最終導致工作執行緒Crash掉了*_*

解決方案:
為了解決在主執行緒中Wait的問題,微軟專門設計了一個函式MsgWaitForMultipleObjects,這個函式即可以等待訊號(thread,event,mutex等等),也可以等待訊息(MSG)。即不論有訊號被激發或者有訊息到來,此函式都可以返回。呵呵,那麼我的解決辦法也就出來了。
將上面的WaitForSingleObject用下面的程式碼替換:
while
(TRUE)
{

    DWORD result ; 
    MSG msg ; 

    result 
= MsgWaitForMultipleObjects(1&readThreadHandle, 
        FALSE, INFINITE, QS_ALLINPUT); 

    
if (result == (WAIT_OBJECT_0))
    
{
        
break;
    }
else
        PeekMessage(
&msg, NULL, 00, PM_REMOVE);
        DispatchMessage(
&msg); 
    }
 
}


總結:
如果在工作執行緒中有可能涉及到了訊息驅動的API,那麼不能在主執行緒中使用WaitForSingleObject一類函式,而必須使用上述的方案。

相關推薦

執行慎用WaitForSingleObject (WaitForMultipleObjects) --代替方法MsgWaitForMultipleObjects

下面的程式碼我除錯了將近一個星期,你能夠看出什麼地方出了問題嗎? 執行緒函式:  DWORD WINAPI ThreadProc(      while ( ! bTerminate)      {          //  從一個連結串列中讀取資訊並且插入到CListCtrl中         

Android面試執行的Looper.loop()一直無限迴圈為什麼不會造成ANR?(轉)

  引子: 正如我們所知,在android中如果主執行緒中進行耗時操作會引發ANR(Application Not Responding)異常。 造成ANR的原因一般有兩種: 只有當應用程式的UI執行緒響應超時才會引起ANR,超時產生原因一般有兩種 1. 當前的事件沒有機會

android執行Looper.loop()為什麼不會造成程式ANR

程式入口為ActivityThread的main方法,原始碼如下: frameworks/base/core/java/android/app/ActivityThread.java public static void main(String[] args) { S

Qt通過訊號和槽在子執行執行進行資料傳遞

QT中兩個執行緒之間進行自定義型別資料傳遞 兩個執行緒中進行資料傳遞時,傳遞的資料放到佇列中(queue),所以在這個過程中,需要在傳遞前將資料拷貝、儲存到佇列中;為了儲存這些引數,Qt需要construct、destruct、copy這些物件,為了讓Qt知道

[轉]Android限制只能在執行進行UI訪問的實現原理

目錄 Android限制只能在主執行緒中進行UI訪問 Thread的實現 Android Thread 的構造方法 Android Thread 的start()方法 如何在我們自己的程式碼中去檢測當前Thread是不是UI執

WebTool 網頁資訊獲取,可在執行呼叫

WebTool.java package sci.tool; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.URL; import java.net.U

執行呼叫執行的start()

public class Quest implements Runnable { int b = 100; public synchronized void m1() throws Exception { System.out.println("en

Handler訊息傳遞機制(子執行傳遞new Handler和執行new Handle傳遞訊息)

> 子執行緒中更新UI new Thread(new Runnable() {         @Override         public void run() {             Looper.prepare();          

Android為什麼執行不會因為Looper.loop()方法造成阻塞

很多人都對Handler的機制有所瞭解,如果不是很熟悉的可以看看我 如果看過原始碼的人都知道,在處理訊息的時候使用了Looper.loop()方法,並且在該方法中進入了一個死迴圈,同時Looper.loop()方法是在主執行緒中呼叫的,那麼為什麼沒有造成阻

Android執行延時處理

Android對UI主執行緒開啟了實時監聽,Activity Manager和WindowManager系統服務一旦監聽到主執行緒超過10秒沒有響應操作,就會丟擲ANR,所以,在UI主執行緒中不能直接呼叫Thread.sleep方法去延時,超過10秒就根本不會執

Android 幾種非同步方式,解決執行遇到的卡頓

起因: 當我們的UI越來越複雜的時候,或者說某個業務需要大量的計算的時候,我們的主執行緒會消耗大量的資源去計算,這個時候,我們的Activity或者說fragmemt等UI頁面就會出現卡頓,乃至ANR。總結一下,就是我們直接在主執行緒(UI執行緒)中,做耗時操作,就會造成卡

關於執行自動建立的Looper的思考:執行Looper的輪詢死迴圈為何沒有阻塞執行

Android中UI執行緒會自動給我們建立一個looper,但是looper中的loop方法是個死迴圈.為什麼我們在UI執行緒中寫的程式碼為何都能順利執行?為什麼沒有引起ANR呢? Looper的部分原始碼: /** * Initial

handle.post 跳到執行執行

package com.example.che; import android.os.Bundle; import android.os.Handler; import android.app.Activity; import android.widget.T

執行的Looper.loop()一直無限迴圈為什麼不會造成ANR?

引子: 正如我們所知,在android中如果主執行緒中進行耗時操作會引發ANR(Application Not Responding)異常。 造成ANR的原因一般有兩種: 當前的事件沒有機會得到處理(即主執行緒正在處理前一個事件,沒有及時的完成或者looper被某種原因阻塞住了)當前的事件正在處理,但沒有

Handler.post(Runable),Runable是執行執行的。

 在Android中可以通過handler方法完成資料的執行緒間的傳遞,但一定要將handler得到的資料通過loop傳遞到主執行緒再更新UI嗎?其實也可以直接使用handler設計的post方法進行

Handler寫在執行,使用Message傳遞訊息

Runnable是一個介面,Thread是Runnable的子類。 Message Message 是線上程之間傳遞的訊息,它可以在內部攜帶少量的資訊,用於在不同執行緒之間交換資料。 Ha

Looper機制執行利用handler向工作執行傳送訊息

注意:由主執行緒向非UI執行緒中傳送訊息的時候,非UI執行緒需要先新增訊息佇列,然後處理訊息迴圈。 (1).預設情況下android中新誕生的執行緒是沒有開啟訊息迴圈的。(主執行緒除外,主執行緒系統會自動為其建立Looper物件,開啟訊息迴圈。)

NSTimer直接使用需要在執行使用

NSTimer 的 scheduledTimerWithTimeInterval  方法使用時需要在主執行緒中使用否則不會執行的。 1. NSRunLoopCommonModes和Timer     當使用NSTimer的scheduledTimerWithTime

用Handler的post()方法來傳遞執行的程式碼段到執行執行

package com.kale.handler; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android

執行Thread.Sleep()是否會導致ANR

前言: 1.對Thread.sleep(long duration)的認知。     &