2008-10-23 14 views
8

मेरा आवेदन कई सूत्र है: 1) मुख्य थ्रेड 2) 2 उप मुख्य धागे (संदेश लूप के साथ प्रत्येक, जिन्हें आप नीचे), TFQM 3) एन कार्यकर्ता धागे (सरल द्वारा प्रयोग किया जाता लूप, जिसमें नींद())डेल्फी मल्टी-थ्रेडिंग संदेश लूप

मेरी समस्या यह है कि, जब मैं अपना आवेदन बंद करता हूं, तो वर्कर थ्रेड्स ठीक से बाहर निकलने का प्रबंधन करते हैं, लेकिन 2 उप-मुख्य थ्रेड्स में से 1 लटकता है (कभी बाहर नहीं निकलता है) जब मैं उन्हें बंद करने के लिए WM_QUIT जारी करता हूं ।


procedure ThreadProcFQM(P: Integer); stdcall; 
var 
    Msg: TMsg; 
_FQM: TFQM; 
begin 
    _FQM := Ptr(P); 
    try 
    _FQM.fHandle := AllocateHwnd(_FQM.WndProc); 

    while GetMessage(Msg, 0, 0, 0) do 
    begin 
     TranslateMessage(Msg); 
     DispatchMessage(Msg); 
    end; 

    finally 
    DeallocateHWnd(_FQM.fHandle); 
    SetEvent(_FQM.hTerminated); 
    end; 
end; 

procedure TFQM.Stop; 
begin 
    PostMessage(fHandle, WM_QUIT, 0, 0); 

    WaitForSingleObject(hTerminated, INFINITE); 
    if hThread <> INVALID_HANDLE_VALUE then 
    begin 
    CloseHandle(hThread); 
    hThread := INVALID_HANDLE_VALUE; 
    end; 
end; 

उत्तर

9

मैं एक ही समस्या थी गया है, और मुझे पता चला मैं एक छिपा खिड़की सिर्फ संदेशों प्राप्त करने के लिए नहीं बनाना चाहिए। थ्रेड में पहले से ही एक संदेश प्रणाली है।

मुझे लगता है कि आप अपने विंडोज हैंडल बना रहे हैं और इसे एफएचंडल में स्टोर करते हैं, लेकिन GetMessage आपके थ्रेड के संदेश लूप को चेक करता है। इसलिए संदेश पोस्टमेसेज (fHandle, WM_QUIT, 0, 0); गेटमेसेज द्वारा कभी प्राप्त नहीं किया जाता है।

आप पोस्ट थ्रेड मैसेज का उपयोग करके अपने धागे पर संदेश पोस्ट कर सकते हैं, और थ्रेड में आप GetMessage (CurrentMessage, 0, 0, 0) का उपयोग कर सकते हैं। केवल महत्वपूर्ण अंतर आपको बुला रहा

PeekMessage(CurrentMessage, 0, WM_USER, WM_USER, PM_NOREMOVE); 

आप इस साथ शुरू करना चाहिए की तुलना में अपने स्थापना करते हैं और की तुलना में अपने पाश शुरू करके अपने धागे से संदेश पाश शुरू करने के लिए होता है।

आपको चोटी संदेश से शुरू करने का कारण यह सुनिश्चित करना है कि आपके थ्रेडप्रोसेडर के प्रारंभ के दौरान भेजे गए संदेश खो जाएंगे।

अजीब बात यह है कि फिलहाल मुझे उस संदर्भ को नहीं मिला जहां मैंने यह सीखा, लेकिन मेरा अनुमान न्यूज़ ग्रुप समुदाय है।

+0

ओउप्स, मेरी पहली बार खेद है। टिप्पणियों के बारे में नहीं पता था .... मैं इसे आज़मा दूंगा। धन्यवाद। – Atlas

+0

डेवी सही है: संदेश कतार – Remko

+0

बनाने के लिए PeekMessage का उपयोग किया जाना चाहिए [इसे 'पोस्ट थ्रेड मैसेज' के लिए [एमएसडीएन पृष्ठ] पर पढ़ें [http://msdn.microsoft.com/en-us/library/ms644946 (VS.85) .aspx)। वे यह भी सिफारिश करते हैं कि मुख्य थ्रेड किसी ईवेंट पर प्रतीक्षा करें जो थ्रेड सेट हो जाने पर एक बार संदेश बनाया गया हो। –

6

1) आपको अपने धागे के भीतर AllocateHwnd में आवश्यकता नहीं है। GetMessage पर पहला कॉल इस धागे के लिए एक अलग संदेश कतार बनाएगा। लेकिन धागे को संदेश भेजने के लिए आपको PostThreadMessage फ़ंक्शन का उपयोग करना चाहिए।

ध्यान रखें कि PostThreadMessage को कॉल करने के समय कतार अभी भी नहीं बनाई जा सका। मैं आम तौर पर निर्माण का उपयोग करता हूं:

while not PostThreadMessage(ThreadID, idStartMessage, 0, 0) do 
    Sleep(1); 

संदेश कतार बनाने के लिए यह सुनिश्चित करने के लिए।

idExitMessage = WM_USER + 777; // you are free to use your own constant here 

3) अलग घटना के लिए कोई जरूरत नहीं है, क्योंकि आप WaitForSingleObject कार्य करने के लिए धागा संभाल पारित कर सकते हैं:

2) धागा पाश समाप्त के लिए मैं अपने खुद के संदेश को परिभाषित। तो, अपने कोड दिखाई दे सकता है जैसे:

PostThreadMessage(ThreadID, idExitMessage, 0, 0); 
    WaitForSingleObject(ThreadHandle, INFINITE); 

विचार यह है कि threadid और ThreadHandle विभिन्न मूल्यों हैं में ले लो।

4) तो, अपने ThreadProc तरह दिखेगा:

procedure ThreadProcFQM; stdcall; 
var 
    Msg: TMsg; 
begin 
    while GetMessage(Msg, 0, 0, 0) 
    and (Msg.Message <> idExitMessage) do 
    begin 
    TranslateMessage(Msg); 
    DispatchMessage(Msg); 
    end; 
end; 
+0

धन्यवाद, मैं इसे आज़मा दूंगा। – Atlas

+0

जैसा कि नीचे बताया गया है, आपको PeekMessage के साथ संदेश कतार बनाना चाहिए: // फोर्स संदेश कतार निर्माण PeekMessage (संदेश, 0, WM_USER, WM_USER, PM_NOREMOVE); – Remko

11

मैं अपने कोड में कुछ समस्याओं को इंगित कर सकते हैं ...

1) आप AllocateHwnd के उत्पादन की जाँच नहीं कर रहे हैं। हां, शायद यह कभी असफल नहीं होगा, लेकिन फिर भी ...

2) AllocateHwnd belogs कोशिश करने के बाहर .. आखिरकार! यदि यह विफल रहता है, तो DeallocateHwnd को नहीं बुलाया जाना चाहिए।

3) AllocateHwnd थ्रेडसेफ नहीं है। यदि आप इसे एक साथ कई धागे से कॉल करते हैं, तो आप पोबलेम्स में भाग सकते हैं। Read more.

जैसा डेवी ने कहा, छुपा संदेश विंडो बनाने के बजाय MsgWaitForMultipleObjects का उपयोग करें। फिर थ्रेड पर संदेश भेजने के लिए PostThreadMessage का उपयोग करें।

यदि मैं यहां एक पूरी तरह से मुक्त उत्पाद के लिए प्लग डाल सकता हूं - इसके बजाय मेरे OmniThreadLibrary का उपयोग करें। विंडोज मैसेजिंग के साथ सीधे गड़बड़ करने से बहुत आसान है।

+0

गेबर, धन्यवाद, लेकिन आपकी lib केवल डी 2006 + तक ही सीमित है? मैं डी 7 का उपयोग कर रहा हूं .... – Atlas

+0

डी 2007 +, वास्तव में। अपग्रेड करने का समय, फिर :) – gabr

+0

गैबर, आपकी थ्रेडिंग लाइब्रेरी शानदार दिखती है - इसे इंगित करने के लिए धन्यवाद। ओह, और मैं कहूंगा कि आपकी साइट "स्पार्टन" है, बदसूरत नहीं। – Argalatyr

संबंधित मुद्दे