線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1260
推到 Plurk!
推到 Facebook!

如何避免windows message 重入的問題

尚未結案
Snooze
一般會員


發表:18
回覆:21
積分:7
註冊:2002-06-03

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-08-26 12:37:01 IP:61.220.xxx.xxx 未訂閱
下面code 是當有drive letter 新增或移除的時候 會分別Add sltDevADD 與 sltDevRmv 兩個StringList    
 
unit Unit1;    interface    uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;    const
  DBT_DEVICEARRIVAL = $8000; //硬體裝置完成安裝
  DBT_DEVICEREMOVECOMPLETE = $8004; //硬體裝置已經移除    type
  PDevBroadcastVolume = ^TDevBroadcastVolume;
  TDevBroadcastVolume = packed record
    dbcv_size: DWORD;
    dbcv_devicetype: DWORD;
    dbcv_reserved: DWORD;
    dbcv_unitmask: DWORD;
    dbcv_flags: Word;
  end;      TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure WMDeviceChange(var Msg: TMessage); message WM_DeviceChange;
  end;    var
  Form1: TForm1;
  sltDevADD: TStringList;
  sltDevRmv: TStringList;    implementation    {$R *.dfm}    function GetDrive(pDBVol: PDevBroadcastVolume): string;
var
  i: Byte;
  Maske: DWORD;
begin
//  if (pDBVol^.dbcv_flags and DBTF_Media) = DBTF_Media then
  begin
    Maske := pDBVol^.dbcv_unitmask;
    for i := 0 to 25 do
    begin
      if (Maske and 1) = 1 then
        Result := Char(i   Ord('A'))   ':';
      Maske := Maske shr 1;
    end;
  end;
end;    procedure TForm1.WMDeviceChange(var Msg: TMessage);
begin
  case Msg.wParam of
    DBT_DeviceArrival: begin
                           if PDevBroadcastVolume(Msg.lParam).dbcv_flags <> $0001 then
                               sltDevADD.Add(  GetDrive(PDevBroadcastVolume(Msg.lParam))  );
                       end;
    DBT_DeviceRemoveComplete: begin
                           if PDevBroadcastVolume(Msg.lParam).dbcv_flags <> $0001 then
                               sltDevRmv.Add(  GetDrive(PDevBroadcastVolume(Msg.lParam))  );
                       end;
  end;    end;    procedure TForm1.FormCreate(Sender: TObject);
begin
  sltDevADD := TStringList.Create;
  sltDevRmv := TStringList.Create;
end;    end.
但問題是我發現 當新增Drive Letter 時會同時好幾筆近來的狀況 比如插入usb 隨身碟 DBT_DeviceArrival 會收到三次 我嘗試用boolean 變數阻擋重入但實際上還是太快 檔不掉,有人有愈過同樣的問題嗎? Nice to meet u
------
Nice to meet u
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-09-06 22:23:13 IP:211.76.xxx.xxx 未訂閱
我先聲明,我沒有寫過類似您 drive letter 新增/移除的程式, 不過,對於重入問題及 Windows Message 處理的部分, 之前有提問過以下問題:    ■【問題】什麼是 Thread-Safe 及如何測試?  http://delphi.ktop.com.tw/topic.php?TOPIC_ID=49776 ■【問題】如何解決多執行緒重入及鎖定的問題  http://delphi.ktop.com.tw/topic.php?TOPIC_ID=49583 ■【BCB】【問題】如何防止重入? (含問題程式)  http://delphi.ktop.com.tw/topic.php?TOPIC_ID=49478    而我目前的認知是,以您的程式寫法,應該不會有重入的問題, 因為系統一次只會處理一個 Message ,在這個 Message 還沒處理完之前, 不會離開處理函式,除非在處理函式內使用了 Application.ProcessMessages 但您的程式內並沒有,所以,應該不會有重入的問題。 如果會的話,那在這篇中: ■【問題】什麼是 Thread-Safe 及如何測試?  http://delphi.ktop.com.tw/topic.php?TOPIC_ID=49776 就不能說事件以 post/send message 的方式,交由主執行緒來執行, 同時在事件中可以叫用任何 VCL 元件。    如果, Windows Message 不會重入,那只是如何設計一個方式可以解決 收到重覆 Message 的處理。 對於 sltDevADD, sltDevRmv 這兩個 TStringList 可以設定 Duplicates:=dupIgnore; 自動濾除重覆的字串, 另外,再一個 Timer 固定時間比對 sltDevADD, sltDevRmv 來判斷目前到底有多或少那些磁碟。    或是用一個  TStringList 即可,一樣設 Duplicates:=dupIgnore; 而在 DBT_DeviceArrival 作 Add(),  在 DBT_DeviceRemoveComplete 找出那個字串,然後刪除它, 這樣,這個 List 就可以是目前可移除裝置的列表了。    StatPlus2 視動科技 VMASK - ViewMove Automation Software Kernel
------
http://www.ViewMove.com
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-09-07 22:00:31 IP:61.64.xxx.xxx 未訂閱
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=49757
系統時間:2024-05-07 16:41:23
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!