2010-02-16 8 views
5

मैं थोड़ा सा गड़बड़ है जो एक अनुप्रयोग में प्रगति पट्टी मुद्दा हल करने के लिए एक पैच कर रहा हूँ। भारी काम करने वाले धागे पर Thread.Abort करने के लिए प्रयुक्त प्रगति पट्टी पर रद्द किया गया था। मैंने बदल दिया कि एक रद्द ध्वज उठाने के लिए कि मैं धागे में रणनीतिक जगह पर जांच कर सकता हूं।मुख्य धागे भूख से बचने के लिए कैसे?

अधिकांश समय यह ठीक काम करता है लेकिन थोड़ी देर में रद्दीकरण बिल्कुल काम नहीं करता है। मुझे लगता है कि मैं ध्वज की स्थिति को देखने से पहले Application.DoEvents कर सकता हूं (पुन: प्रयास करने का कोई खतरा नहीं है) लेकिन मुझे एक और "साफ" विकल्प चाहिए।

मैं सराहना करता हूं कि कोई मुझे यह समझने के लिए जानकारी प्रदान कर सकता है कि वास्तव में क्या चल रहा है और यह सामान दृश्य के पीछे कैसे काम करता है। मैं जानना चाहता हूं कि BackgroundWorker (जैसे आप .NET 1.1 में) के बिना इस समस्या से निपटने के लिए कैसे चाहते हैं, लेकिन मैं यह भी जानना चाहूंगा कि BackgroundWorker उस तरह की समस्याओं को हल करता है और यह कैसे करता है।

संपादित करें: मैं आपके सुझावों का नोट ले रहा हूं और कल कुछ कोशिश करूँगा और रिपोर्ट करूंगा। मैंने पहली बार एक अस्थिर बूल का इस्तेमाल किया, मुझे लगता है कि मैंने इसे एक स्वचालित संपत्ति में अपडेट किया है और अस्थिरता के बारे में भूल गया है। क्या कार्यकर्ता थ्रेड कैश किए गए मान को बार-बार देख सकता है? मैं नहीं देखता कि मैं कैसे मृत्यु कर सकता हूं। मजदूर ध्वज की जांच करने के बाद से मैं ब्रेकपॉइंट ऑन-द-फ्लाई लगाकर वहां तोड़ने में कामयाब रहा। मैं हमेशा डेटा के उसी सेट के साथ परीक्षण करता हूं और अधिकांश समय यह ठीक से रद्द करता है। एकमात्र चीज जो परीक्षणों के बीच बदलती है वह क्षण है जब मैं रद्द करता हूं। अब तक, मैंने केवल डीएसबी से शुरू किया, डीएस से शुरू किया।

संपादित करें 2: यह पता चला है कि मेरा मुद्दा मेरे ध्वज या जो भी मैंने जोड़ा है उससे संबंधित नहीं है। यह WinForm समस्या का अधिक है। कार्यक्रम ShowDialog पर कॉल करने के लिए मिलता है (और पहले से ही एक और ShowDialog अवरुद्ध है)। मैं फॉर्म को खींच नहीं सकता और यह स्वयं ही ताज़ा नहीं होता है। उस पर रद्द बटन भी काम नहीं करता है। जब मैं सबकुछ रोकता हूं तो यहां कॉल स्टैक होता है।

 
[Code externe] 
    Mrnf.Son.Commun.dll!Mrnf.Son.Commun.Messages.BarreProgressionBase.ShowDialog(System.Windows.Forms.IWin32Window fenetre = {Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm}) Ligne 274 + 0xb octets C# 
    Mrnf.Son.Commun.dll!Mrnf.Son.Commun.Controleurs.Utils.AttendreFinTraitement(System.Windows.Forms.Form parent = {Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm}, Mrnf.Son.Commun.Messages.BarreProgressionBase progressionBase = {Mrnf.Son.Commun.Messages.BarreProgressionMessage}, System.Threading.Thread thread = {System.Threading.Thread}) Ligne 302 + 0xd octets C# 
    Mrnf.Son.Affaires.dll!Mrnf.Son.Affaires.Persisteurs.Echanges.LecteurDBFGeneriqueCollection.Importer(System.Windows.Forms.Form parent = {Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm}) Ligne 95 + 0x1d octets C# 
    Mrnf.Son.Affaires.dll!Mrnf.Son.Affaires.Persisteurs.Echanges.PersisteurModeleEchanges.Importer(Mrnf.Son.Affaires.Entites.Echanges.ModeleEchanges unModele = {Mrnf.Son.Presentation.Windows.Controleurs.Echanges.ModeleEchanges.ModeleEchangesGenerique}, System.Windows.Forms.Form formParent = {Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm}) Ligne 1880 + 0xd octets C# 
    Mrnf.Son.Affaires.dll!Mrnf.Son.Affaires.Entites.Echanges.ModeleEchanges.Importer(System.Windows.Forms.Form formParent = {Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm}) Ligne 875 + 0x18 octets C# 
    Mrnf.Son.Presentation.Windows.exe!Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm.EffectuerImport(Mrnf.Son.Affaires.Entites.Echanges.IModeleEchanges modele = {Mrnf.Son.Presentation.Windows.Controleurs.Echanges.ModeleEchanges.ModeleEchangesGenerique}) Ligne 1429 + 0xc octets C# 
    Mrnf.Son.Presentation.Windows.exe!Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm._terminerBtn_Click(object sender = {Text = Impossible d'évaluer l'expression, car un frame natif se trouve en haut de la pile des appels.}, System.EventArgs e = {System.EventArgs}) Ligne 1334 + 0x1d octets C# 
[Code externe] 
    Mrnf.Son.Presentation.Windows.exe!Mrnf.Son.Presentation.Windows.UI.Echanges.AssistantForm.WndProc(ref System.Windows.Forms.Message m = {System.Windows.Forms.Message}) Ligne 1133 + 0xb octets C# 
[Code externe] 
    Mrnf.Son.Presentation.Windows.exe!Mrnf.Son.Presentation.Windows.Controleurs.Sondages.ActionsSondages.OnImporterSysExt() Ligne 1362 + 0x1f octets C# 
    Mrnf.Son.Presentation.Windows.exe!Mrnf.Son.Presentation.Windows.UI.Sondages.UEExploitationVue._mniImporterSysExt_Click(object sender = {System.Windows.Forms.ToolStripMenuItem}, System.EventArgs e = {System.EventArgs}) Ligne 820 + 0x12 octets C# 
[Code externe] 
    Mrnf.Son.Presentation.Windows.exe!Mrnf.Son.Presentation.Windows.Program.Main() Ligne 148 + 0x8 octets C# 
[Code externe] 

संपादित करें 3: अगर मैं ShowDialog को null पारित यह ठीक काम करता है (यूआई जमता नहीं, बटन काम करता है रद्द, यह ठीक रद्द)। मैं वास्तव में इस सब के पीछे जादू को समझ नहीं पा रहा हूं।

उत्तर

1

अन्य पोस्ट शायद इस पर क्यों ट्रैक कर रहे हैं।

मुझे थ्रेड.जॉइन()/थ्रेड.एबॉर्ट() के साथ संयोजन में WaitHandles का उपयोग करना पसंद है जब मैं थ्रेड को मारने की कोशिश कर रहा हूं।

private readonly ManualResetEvent _ExitThreadsEvent = new ManualResetEvent(false); 
private Thread _MyThread; 

public void Stop() 
{ 
    _ExitThreadsEvent.Set(); 

    if (_MyThread != null) 
    { 
     if (!_MyThread.Join(5000)) 
     { 
      _MyThread.Abort(); 
     } 

     _MyThread = null; 
    } 
} 

private void MyThread() 
{ 
    if (!_ExitThreadsEvent.WaitOne(1)) 
    { 
     // Do some work... 
    } 

    if (!_ExitThreadsEvent.WaitOne(1)) 
    { 
     // Do some more work... 
    } 
} 

शायद आपके मूल डेडलॉक मुद्दे को समझने के लिए भी अच्छा है।

+0

क्या उस स्थिति में 'अस्थिर' ध्वज पर 'मैनुअल रीसेट इवेंट 'का उपयोग करने का कोई फायदा है? यदि आवश्यक हो तो अवरुद्ध करने की संभावना के अलावा (जो मैं नहीं करता), मुझे कोई नहीं दिखाई देता है। –

+0

मैं इसका उपयोग करता हूं क्योंकि यह विशेष रूप से एक या अधिक धागे को सिग्नल करने के लिए डिज़ाइन किया गया है और सही तरीके से लागू करने पर अधिक विचार नहीं करता है। कुल मिलाकर यह एक अस्थिर ध्वज की तुलना में शायद "भारी" है। दोनों काम करेंगे मैं सिर्फ एक दूसरे को पसंद करता हूं :-) –

+0

ठीक है। मेरा मुद्दा स्पष्ट रूप से एक डेडलॉक है जो मेरे संशोधन से संबंधित नहीं है। बटन पर 'ShowDialog' को कॉल करते समय मैं डेडलॉक पहले से ही एक संवाद में क्लिक करता हूं। मुझे लगता है कि ShowDialog को कई कॉल खराब है। संपादित करें: हम उन ShowDialog पर अवरुद्ध होने की उम्मीद करते हैं लेकिन फिर भी इस पर रद्द बटन जैसे ईवेंट को संसाधित करने में सक्षम हैं। –

4

BackgroundWorker कुछ भी अतिरिक्त कुछ भी नहीं करता है, उस स्थान को आसानी से चेक स्थान में प्रदान करने के अलावा। तो वहाँ कुछ संभावनाएं हैं:

  • अपने कोड झंडा जाँच करने के लिए हो रही है, लेकिन देख नहीं है कि यह बदल गया है (सैद्धांतिक रूप से संभव है, तो झंडा सिंक्रनाइज़ है नहीं या अस्थिर है, लेकिन गैर तुच्छ कोड में बहुत संभावना नहीं)
  • अपने कोड झंडा जाँच करने के लिए हो रही है नहीं है

हम बाद के मान लेंगे; कि के कुछ सामान्य कारणों:

  • अगर आप गलती से अपने आप को deadlocking कर रहे हैं (शायद वापस यूआई धागा जो पहले से ही एक पृष्ठभूमि थ्रेड के लिए प्रतीक्षा कर रहा है के लिए Invoke की कोशिश कर रहा है, या एक ताला के चारों ओर एक लूप में हो रही या समान)
  • आप कॉम (या समान) से बाहर बुला रहे हैं, और कहा कि कॉल कभी नहीं पूरा कर रहा है - कुछ मामलों

आप को कम कर सकते हैं इन यह है की, जिसमें से बचने के लिए एक विशेष रूप से कठिन परिदृश्य?शायद अंतराल पर आपका धागा क्या कर रहा है, यह ट्रैक करने के लिए कुछ कोड इंजेक्ट करें, और सुनिश्चित करें कि यह कुछ उपयोगी कर रहा है - या यदि नहीं, तो ट्रैक करें कि यह कहां फंस रहा है।

2

आवेदन। डॉवेंट्स संदेश पंप में लंबित घटनाओं को संसाधित करने की अनुमति देने का माध्यम है। आम तौर पर आपके पृष्ठभूमि धागे से बिल्कुल कुछ नहीं करना चाहिए।

अगर रद्द 'बिल्कुल काम नहीं करता है', तो समाधान काफी हद तक निर्भर करेगा कि 'बिल्कुल भी काम नहीं करता है'। क्या आप ध्वज बदलने में असमर्थ हैं? यूआई अटक गया है? क्या पृष्ठभूमि धागा ध्वज चेन का जवाब नहीं देता है? क्या यह कुछ और है? समाधान प्राथमिक रूप से समस्या पर निर्भर करता है। यह हो सकता है कि आप पृष्ठभूमि से ध्वज की जांच नहीं कर रहे हैं, यह हो सकता है कि आप दो धागे को डेडलॉक करें। कोड दिखा रहा है, या समस्या विवरण विस्तार से मदद मिलेगी।

2

यह डीबग करना लगभग हमेशा आसान होता है। जब आप रद्द अनुरोध को अनदेखा करते हुए कार्यकर्ता धागा देखते हैं, तो डीबग + ब्रेक ऑल का उपयोग करें। फिर डीबग + विंडोज + थ्रेड और वर्कर थ्रेड पर डबल-क्लिक करें। फिर कॉल स्टैक को देखने के लिए देखें कि थ्रेड क्या कर रहा है और यह ध्वज की जांच करने वाले कोड से गुजरता नहीं है।

सावधान रहें कि आपको अस्थिर कीवर्ड के साथ ध्वज सदस्य घोषित करना है। यह जेआईटी कंपाइलर को मशीन कोड उत्पन्न करने से रोकता है जो एक रजिस्टर में सदस्य मूल्य लोड करता है और स्मृति में वास्तविक चर मूल्य की जांच नहीं करता है। जब आप डीबगर के बिना अपने प्रोग्राम के रिलीज़ संस्करण को चलाते हैं तो ऐसा करने के लिए उत्तरदायी होता है। उस स्थिति में, ब्रेक ऑल कमांड का उपयोग करने से पहले डीबगर संलग्न करने के लिए टूल्स + अटैच करने के लिए प्रक्रिया का उपयोग करना सुनिश्चित करें।

एक मैनुअल रीसेट, एक प्रतीक्षाऑन (0) कॉल के साथ चेक किया गया है बेहतर है।

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