เมื่อเขียนโปรแกรมคุณจะพบปัญหากับการสื่อสารระหว่างข้อความ (tform) และข้อความเธรด (tthread) เสมอ สิ่งที่น่ารำคาญคือแบบฟอร์มไม่สามารถส่งข้อความไปยังเธรด (tthread) (เธรดไม่มีที่จับหน้าต่าง) หลังจากทำงานหนักหลายวันฉันก็หาวิธีแก้ปัญหาสองวิธีและพาพวกเขาออกไปพูดคุยกับคุณ
อันดับแรก. เรารู้ว่าไลบรารีคลาส MFC ใน VC ++ มีการประมวลผลข้อความที่ห่อหุ้ม (englicymessage, endmessage) ตารางการแมป (การประมวลผลข้อความเป็นหลักการเรียกใช้วิธีการหรือกระบวนการ) รวมถึงกลไกการแจกแจงข้อความเพื่อรับรู้การรับและการส่งข้อความ <ดู VC ++ ด้านเทคนิคภายใน> สำหรับรายละเอียด ดังนั้นเราเพียงแค่ต้องสร้างตารางการแมปข้อความสำหรับเธรดและสร้างกลไกการกระจายข้อความที่สอดคล้องกัน สิ่งนี้ช่วยให้คุณสามารถประมวลผลข้อความที่ส่งโดยแบบฟอร์มไปยังเธรด รหัสต่อไปนี้เป็นคลาสที่ใช้ตารางการแมปข้อความและการแจกแจงข้อความ (ดู <../ การออกแบบการประมวลผลข้อความ (เธรด) 1/messagehandle.pas> สำหรับรายละเอียด)
Unit Message Handle;
ส่วนต่อประสาน
ใช้ข้อความ, คลาส, sysutils, กล่องโต้ตอบ;
const pmsg_base = $ be00;
pmsg_num = 200;
{** คลาสการประมวลผลข้อความที่กำหนดเอง
*; function = สร้างตารางข้อความที่กำหนดเองและกระบวนการระหว่างเธรด
* และข้อความที่กำหนดเองด้วยแบบฟอร์มหลัก (มาโคร)
-
// ที่จับการประมวลผลข้อความ
tMessageHandle = ขั้นตอน (ข้อความ var: tMessage) ของวัตถุ;
tpDispatcher = คลาส (tobject)
ส่วนตัว
// ข้อความที่สอดคล้องกันของข้อความ (รหัสข้อความเป็นตัวห้อยอาร์เรย์);
MessageHandles: อาร์เรย์ของ TMessageHandle;
// รับรหัสอาร์เรย์จากรหัสข้อความ
ฟังก์ชั่น getindexfrommsgid (const amessageid: cardinal): จำนวนเต็ม;
สาธารณะ
ตัวสร้างสร้าง;
Destructor ทำลาย;
// ส่งข้อความ
โพรซีเดอร์ SendMessage (VAR Message: TMessage);
// เพิ่มข้อความที่กำหนดเองลงในตารางที่สอดคล้องกัน
ขั้นตอน addhandle (const amessageid: cardinal; amessagehandle: tmessagehandle);
จบ;
-
การดำเนินการ
{tpDispatcher}
Constructor tpdispatcher.create;
var i: จำนวนเต็ม;
เริ่ม
SetLength (MessageHandles, PMSG_NUM);
// เริ่มต้นคิวข้อความ;
สำหรับ i: = 0 ถึง pred (pmsg_num) ทำ
MessageHandles [i]: = nil;
จบ;
destructor tpdispatcher.destroy;
เริ่ม
{Table Release Message Table}
Freeandnil (MessageHandles);
จบ;
ขั้นตอน tpdispatcher.addhandle (const amessageid: พระคาร์ดินัล;
AmessageHandle: TMessageHandle);
var tid: จำนวนเต็ม;
เริ่ม
TID: = getIndexfrommsgid (amessageId);
ยืนยัน ((tid> 0) หรือ (tid <pred (pred (pmsg_num)));
ยืนยัน (ได้รับมอบหมาย (amessageHandle));
MessageHandles [TID]: = AmessageHandle;
จบ;
ฟังก์ชั่น tpdispatcher.getIndexfrommsgid (const amessageId: พระคาร์ดินัล): จำนวนเต็ม;
เริ่ม
ผลลัพธ์: = amessageId - pmsg_base;
จบ;
ขั้นตอน tpDispatcher.sendMessage (ข้อความ var: tMessage);
var tid: จำนวนเต็ม;
tmsghandle: tmessageHandle;
เริ่ม
TID: = getIndexfrommsgid (message.msg);
ยืนยัน ((tid> 0) หรือ (tid <pred (pred (pmsg_num)));
tmsghandle: = messagehandles [tid];
ถ้าได้รับมอบหมาย (tmsghandle) แล้ว
tmsghandle (ข้อความ);
จบ;
ตอนนี้เราต้องลงทะเบียนข้อความที่กำหนดเองแล้วใช้คลาสการแจกแจงข้อความ (TPDispatcher) เพื่อประมวลผลข้อความเธรด รหัสมีดังนี้ <ดู ../ การออกแบบการประมวลผลข้อความ (เธรด) 1/test/unt1.pas> สำหรับรายละเอียด:
บทที่หน่วย 1
const
{ข้อความเธรดระยะยาวที่กำหนดเอง}
my_message2 = pmsg_base + 02;
พิมพ์
tform1 = คลาส (tform)
addmsglist: tbutton;
Sendthehead: Tbutton;
sendform: tbutton;
Sendother: Tbutton;
ขั้นตอน SendTheAdClick (ผู้ส่ง: TOBJECT);
โพรซีเดอร์แบบฟอร์ม (ผู้ส่ง: tobject);
FORMDESTROY ขั้นตอน (ผู้ส่ง: TOBJECT);
ส่วนตัว
FDISPATCHER: TPDISPATCHER;
fhandle: tphandler;
fthread: tpthread;
สาธารณะ
{ประกาศสาธารณะ}
จบ;
วาจา
Form1: TFORM1;
การดำเนินการ
{$ r *.dfm}
ขั้นตอน tform1.sendtheadclick (ผู้ส่ง: tobject);
var amessage: tmessage;
amessage.msg: = my_message2;
amessage.wparam: = 1;
fdispatcher.sendmessage (amessage);
จบ;
จบ;
ขั้นตอน TFORM1.FormCreate (ผู้ส่ง: TOBJECT);
เริ่ม
{สร้างคลาสแผนที่ข้อความข้อความ}
fdispatcher: = tpdispatcher.create;
fhandle: = tphandler.create;
{สร้างเธรด}
fthread: = tpthread.create (เท็จ);
{เพิ่มข้อความไปยังตารางการแมป}
fdispatcher.addhandle (my_message2, fthread.domessage);
จบ;
ขั้นตอน TFORM1.FormDestroy (ผู้ส่ง: TOBJECT);
var i: จำนวนเต็ม;
เริ่ม
Freeandnil (fdispatcher);
Freeandnil (fhandle);
สำหรับ i: = 0 ถึง 3 ทำ
Freeandnil (fthread [i]);
จบ;
ที่สอง. หน้าต่างสามารถจัดการกับข้อความได้เนื่องจากมีที่จับหน้าต่าง เพื่อให้เธรดจัดการข้อความเราสามารถเพิ่มที่จับหน้าต่างลงในเธรดของคลาสหน้าต่างที่เกี่ยวข้อง (ซอร์สโค้ดอยู่ใน <../ การออกแบบการประมวลผลข้อความ (เธรด) 2 / pthread.pas>)
หน่วย pthread;
ส่วนต่อประสาน
ใช้คลาส, sysutils, windows, ข้อความ, กล่องโต้ตอบ;
const my_message1 = $ bd00 + 01;
พิมพ์
{** คลาสเธรดการประมวลผลข้อความ
*; function = เพิ่มความสามารถในการประมวลผลเธรด
-
tpmsgthread = คลาส (tthread)
ส่วนตัว
// ที่จับหน้าต่าง
fwndhandle: hwnd;
// ข้อมูลข้อมูลหน้าต่าง
fwndclass: wndclass;
// ตัวชี้ไปยังฟังก์ชั่นการโทรกลับหน้าต่าง
FobjectInstance: ตัวชี้;
// เริ่มต้นข้อมูลหน้าต่าง
ขั้นตอนเริ่มต้น;
// สร้างหน้าต่างที่ซ่อนอยู่
ขั้นตอน createWnd;
// ลงทะเบียนหน้าต่างที่ซ่อน
ขั้นตอนการลงทะเบียน;
ขั้นตอนการทำลายล้าง;
// ฟังก์ชั่นการโทรกลับหน้าต่าง
ขั้นตอน PWNDPROC (ข้อความ VAR: TMessage);
ได้รับการคุ้มครอง
ขั้นตอนดำเนินการ;
ขั้นตอน doterminate;
สาธารณะ
ตัวสร้างสร้าง (createSuspended: บูลีน);
คุณสมบัติ wndhandle: hwnd อ่าน fwndhandle เขียน fwndhandle;
จบ;
การดำเนินการ
const wnd_name = 'py20';
{tpmsgthread}
ตัวสร้าง tpmsgthread.create (createSuspended: บูลีน);
เริ่ม
สร้างมรดก (createSuspended);
fwndhandle: = จำนวนเต็ม (ไม่มี);
initwnd;
Registwnd;
CreateWnd;
จบ;
ขั้นตอน tpmsgthread.createwnd;
เริ่ม
ถ้า (wndhandle = จำนวนเต็ม (ไม่มี)) แล้ว
wndhandle: = createWindow (fwndclass.lpszclassname, fwndclass.lpszclassname,
ws_popup หรือ ws_caption หรือ ws_clipsiblings หรือ ws_sysmenu
หรือ ws_minimizebox
GetSystemMetrics (SM_CXSCREEN) Div 2
getSystemMetrics (sm_cyscreen) div 2
0, 0, 0, 0, fwndclass.hinstance, nil);
// แทนที่ฟังก์ชั่นการโทรกลับหน้าต่าง
SetWindowLong (WNDHANDLE, GWL_WNDPROC, Longint (fobjectInstance));
จบ;
ขั้นตอน tpmsgthread.destroywnd;
เริ่ม
unregisterClass (fwndclass.lpszclassname, fwndclass.hinstance);
DestroyWindow (Wndhandle);
จบ;
ขั้นตอน tpmsgthread.doterminate;
เริ่ม
สืบทอด;
Destroywnd;
จบ;
ขั้นตอน tpmsgthread.execute;
เริ่ม
จบ;
ขั้นตอน tpmsgthread.initwnd;
เริ่ม
fwndclass.lpszclassName: = pchar (wnd_name);
fwndclass.hinstance: = handle;
fwndclass.lpfnwndproc: = @defwindowproc;
จบ;
โพรซีเดอร์ tpmsgthread.pwndproc (ข้อความ var: tmessage);
เริ่ม
จบ;
ขั้นตอน tpmsgthread.registwnd;
เริ่ม
fobjectInstance: = classes.makeobjectInstance (PWNDPROC);
if (fwndclass.hinstance <> จำนวนเต็ม (ไม่มี)) จากนั้น
registerclass (fwndclass);
จบ;