首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ Builder 6 子執行緒更新 StringGrid 導致主介面凍結?必須用訊息機制回主執行緒更新 UI

     編輯:程式設計綜合問答

現象

子執行緒直接 `StringGrid->Cells[c][r] = value`,主視窗按鈕點不動、介面假死。

原因

**VCL/FMX 不是執行緒安全的**。UI 控件只能在**建立它們的執行緒(主執行緒)中存取**。子執行緒直接操作控件屬性會導致:訊息佇列阻塞、內部狀態損毀、死鎖、繪製異常。

正確模式:PostMessage / Synchronize / Queue

1. `Synchronize` (阻塞等待,簡單)


// 執行緒類別
class TUpdateThread : public TThread {
    StringGrid* grid; int row, col; AnsiString text;
protected:
    void __fastcall Execute() {
        // 背景運算...
        Synchronize(&UpdateUI); // 切回主執行緒執行 UpdateUI
    }
    void __fastcall UpdateUI() {
        grid->Cells[col][row] = text;
    }
};

2. `Queue` (非阻塞,C++Builder 2009+)


Queue([=](){ grid->Cells[col][row] = text; }); // Lambda 丟回主執行緒佇列

3. 自訂訊息 `PostMessage` (最靈活、跨模組)


// 定義訊息
#define WM_UPDATE_GRID (WM_USER + 100)

// 子執行緒
PostMessage(Form1->Handle, WM_UPDATE_GRID, row, (LPARAM)new AnsiString(text));

// 主視窗訊息處理
MESSAGE void __fastcall OnUpdateGrid(TMessage &Msg) {
    int row = Msg.WParam;
    AnsiString* txt = (AnsiString*)Msg.LParam;
    StringGrid1->Cells[1][row] = *txt;
    delete txt;
}
BEGIN_MESSAGE_MAP
    VCL_MESSAGE_HANDLER(WM_UPDATE_GRID, TMessage, OnUpdateGrid)
END_MESSAGE_MAP(Form1)

參考資源

總結

**子執行緒絕對不能直接碰 UI 控件**。C++ Builder 用 `Synchronize` (阻塞)、`Queue` (非阻塞)、或 `PostMessage` 自訂訊息,將 UI 更新動作**封送回主執行緒**執行。介面凍結即因違反單執行緒 UI 規則。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved