2010-04-23 14 views
7

मेरे पास एक प्रबंधित थ्रेड है जो एक अप्रबंधित कोड में प्रतीक्षा कर रहा है, अवरुद्ध है, (विशेष रूप से, यह नामांकित पाइपसेवरस्ट्रीम.टाइटफ़ोरकनेक्शन() पर कॉल करता है जो अस्थायी रूप से अप्रबंधित कोड में कॉल करता है, और एक टाइमआउट प्रदान करता है)।अप्रबंधित कोड में अवरुद्ध प्रबंधित थ्रेड को कैसे समाप्त करें?

मैं थ्रेड को अच्छी तरह से बंद करना चाहता हूं।

थ्रेड.एबॉर्ट() का कोई प्रभाव नहीं पड़ता है जब तक कि कोड प्रबंधित क्षेत्र में वापस नहीं आ जाता है, जो तब तक नहीं करेगा जब तक कोई ग्राहक कनेक्शन न करे, जिसे हम प्रतीक्षा नहीं कर सकते)।

मुझे अप्रबंधित कोड से "सदमे" की आवश्यकता है; या अप्रबंधित भूमि में होने पर भी धागे को मारने का एक तरीका।

+1

किसी भी कारण से आप NamedPipeServerStream.BeginWaitForConnection() का उपयोग नहीं कर रहे हैं? – SpaceghostAli

+1

मूल रूप से क्योंकि थ्रेड किसी कनेक्शन के लिए "हमेशा के लिए" इंतजार करना चाहता है (जब तक कि शटडाउन न हो)। स्टार्ट/एंड प्रतीक्षाफॉरकनेक्शन के साथ, मुझे शुरुआत करना होगा, एक सेकंड प्रतीक्षा करें, कनेक्शन या टाइमआउट की जांच करें, और टाइमआउट पर लूप करें। –

+1

ठीक है मुझे यह मिल गया। अच्छी तरह से डीटीबी के जवाब में थोड़ा सा संशोधन आपको जो चाहिए वह आपको देना चाहिए। AsyncResult पर प्रतीक्षा करने के बजाय, साझा किए गए वेटहैंडल पर प्रतीक्षा करें जिसे आपने थ्रेड को रोकने के लिए कोड से सेट किया है। – SpaceghostAli

उत्तर

19

क्या आपने गैर-अवरुद्ध NamedPipeServerStream.BeginWaitForConnection विधि का उपयोग करने का प्रयास किया है?

using (NamedPipeServerStream stream = ...) 
{ 
    var asyncResult = stream.BeginWaitForConnection(null, null); 

    if (asyncResult.AsyncWaitHandle.WaitOne(5000)) 
    { 
     stream.EndWaitForConnection(asyncResult); 
     // success 
    } 
} 

आपको एक निश्चित टाइमआउट का उपयोग करने की आवश्यकता नहीं है। आप का संकेत देने वाला ManualResetEvent का उपयोग करते हैं धागा कनेक्शन के लिए प्रतीक्षारत बंद कर देना चाहिए कर सकते हैं:

ManualResetEvent signal = new ManualResetEvent(false); 

using (NamedPipeServerStream stream = ...) 
{ 
    var asyncResult = stream.BeginWaitForConnection(_ => signal.Set(), null); 

    signal.WaitOne(); 
    if (asyncResult.IsCompleted) 
    { 
     stream.EndWaitForConnection(asyncResult); 
     // success 
    } 
} 

// in other thread 
void cancel_Click(object sender, EventArgs e) 
{ 
    signal.Set(); 
} 
+0

सिग्नल को BeginWaitForConnection को पास किए गए कॉलबैक के अंदर भी सेट करने की आवश्यकता है। फिर उदाहरण पूरा हो जाएगा। –

1

कोई रास्ता नहीं करने के लिए "बड़े करीने से" नीचे एक धागा बाहर से, बंद करता है, तो उस सूत्र unmannaged कोड चल रहा है नहीं है। थ्रेड को अचानक समाप्त करने के कुछ तरीके हैं, लेकिन शायद यह नहीं है कि आप क्या चाहते हैं।

आपको इसके बजाय BeginWaitForConnection का उपयोग करना चाहिए।

0

दरअसल, मैंने जिस समाधान का उपयोग किया था (जो मुझे प्रश्न लिख रहा था), सभी थ्रेड को निरस्त करने के बाद, प्रत्येक थ्रेड के लिए क्लाइंट (और तुरंत निपटान) बनाने के लिए था।

threads.ForEach(thread=> thread.Abort()); 
    threads.ForEach(thread=> 
       { 
        var client = new PipeClient(ServiceName); 
        client.Connect(); 
        client.Dispose(); 
       }); 
कनेक्शन के साथ

, यह कोड में कामयाब करने के लिए देता है, और बीच में बंद करें() बज उठती (धागा ThreadAbortException लग जाती है और खुद को साफ)

यह सामान्य मामले के लिए काम नहीं करता है (यानी, शीर्षक में सवाल उठाया गया), लेकिन यह मेरे लिए काम करता है ...

+0

यदि आप इस पागल योजना के साथ जाते हैं, तो कनेक्ट पर उचित टाइमआउट का उपयोग करना सुनिश्चित करें, बस अगर किसी अन्य प्रक्रिया में गलत पल पर कनेक्शन स्थापित होता है, तो सुनने के धागे को निरस्त कर दिया जाता है और यह थ्रेड ब्लॉक हो जाता है! –

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