सवाल ThreadPool.QueueUserWorkItem से अपवाद कैसे प्राप्त करें?


मेरे पास निम्न कोड है जो अपवाद फेंकता है:

ThreadPool.QueueUserWorkItem(state => action());

जब कार्रवाई अपवाद फेंकता है, तो मेरा प्रोग्राम दुर्घटनाग्रस्त हो जाता है। इस स्थिति को संभालने के लिए सबसे अच्छा अभ्यास क्या है?


सम्बंधित: नेट थ्रेडपूल थ्रेड पर अपवाद


44
2018-04-15 21:37


मूल


इस सवाल के साथ आपने अभी अपना जीवन बचाया है;) मेरा आईआईएस दुर्घटनाग्रस्त हो रहा था और मुझे नहीं पता था कि समस्या क्या थी ... यह एक समस्या थी: डी - rpf


जवाब:


यदि आपके पास पहुंच है actionस्रोत कोड, उस विधि में एक कोशिश / पकड़ ब्लॉक डालें; अन्यथा, एक नया बनाएँ tryAction विधि जो कॉल को लपेटती है action एक कोशिश / पकड़ ब्लॉक में।


24
2018-04-15 21:41





आप इस तरह प्रयास / पकड़ जोड़ सकते हैं:

        ThreadPool.QueueUserWorkItem(state =>
                                         {
                                             try
                                             {
                                                 action();
                                             }
                                             catch (Exception ex)
                                             {
                                                 OnException(ex);
                                             }
                                         });

70
2018-04-15 21:43



एक भेड़ के बच्चे के ठंडा उपयोग के लिए +1। मैंने पाया कि अगर थ्रेड पूल में एक वर्कर थ्रेड ने मेरे वेब ऐप में एक अनचाहे अपवाद फेंक दिया, तो यह पूरे वेब सर्वर को क्रैश कर देगा। यह मुझे बचाया! धन्यवाद! - CodingWithSpike
उदाहरण के लिए +1 - CGK
+1 या जान! यह पूरी तरह से अद्भुत दोस्त है! - ppumkin
यह स्वीकार्य उत्तर क्यों नहीं है? - TheAlbear


यदि आप .NET 4.0 का उपयोग कर रहे हैं, तो यह जांच के लायक हो सकता है कार्य कक्षा क्योंकि यह आपके लिए इसका ख्याल रख सकती है।

आपके मूल कोड के बराबर, लेकिन कार्य का उपयोग, ऐसा लगता है

Task.Factory.StartNew(state => action(), state);

अपवादों से निपटने के लिए आप StartNew द्वारा लौटाए गए कार्य में निरंतरता जोड़ सकते हैं। यह ऐसा दिखाई दे सकता है:

var task = Task.Factory.StartNew(state => action(), state);
task.ContinueWith(t => 
     {
        var exception = t.Exception.InnerException;
        // handle the exception here
        // (note that we access InnerException, because tasks always wrap
        // exceptions in an AggregateException)
     }, 
     TaskContinuationOptions.OnlyOnFaulted);

19
2017-09-12 18:51





दूसरे धागे पर, (जिस विधि में आप "क्यूइंग" कर रहे हैं, एक कोशिश पकड़ने का प्रयास करें ... फिर पकड़ में, पकड़े गए अपवाद को एक साझा अपवाद चर (मुख्य थ्रेड पर दृश्यमान) में रखें।

फिर आपके मुख्य धागे में, जब सभी कतारबद्ध वस्तुएं समाप्त हो जाती हैं (इसके लिए एक प्रतीक्षा हैंडल सरणी का उपयोग करें) जांचें कि कुछ धागे ने अपवाद के साथ साझा अपवाद को पॉप्युलेट किया है ... यदि ऐसा होता है, तो इसे फिर से चलाएं या इसे उचित रूप से संभाल लें ...

यहां हालिया प्रोजेक्ट से कुछ नमूना कोड है जिसका मैंने उपयोग किया ...
HasException साझा बूलियन है ...

    private void CompleteAndQueuePayLoads(
           IEnumerable<UsagePayload> payLoads, string processId)
    {
        List<WaitHandle> waitHndls = new List<WaitHandle>();
        int defaultMaxwrkrThreads, defaultmaxIOThreads;
        ThreadPool.GetMaxThreads(out defaultMaxwrkrThreads, 
                                 out defaultmaxIOThreads);
        ThreadPool.SetMaxThreads(
            MDMImportConfig.MAXCONCURRENTIEEUSAGEREQUESTS, 
            defaultmaxIOThreads);
        int qryNo = 0;
        foreach (UsagePayload uPL in payLoads)
        {
            ManualResetEvent txEvnt = new ManualResetEvent(false);
            UsagePayload uPL1 = uPL;
            int qryNo1 = ++qryNo;
            ThreadPool.QueueUserWorkItem(
                delegate
                    {
                        try
                        {
                            Thread.CurrentThread.Name = processId + 
                                                      "." + qryNo1;
                            if (!HasException && !uPL1.IsComplete)
                                 IEEDAL.GetPayloadReadings(uPL1, 
                                                  processId, qryNo1);
                            if (!HasException) 
                                UsageCache.PersistPayload(uPL1);
                            if (!HasException) 
                                SavePayLoadToProcessQueueFolder(
                                             uPL1, processId, qryNo1);
                        }
                        catch (MeterUsageImportException iX)
                        {
                            log.Write(log.Level.Error,
                               "Delegate failed "   iX.Message, iX);
                            lock (locker)
                            {
                                HasException = true;
                                X = iX;
                                foreach (ManualResetEvent 
                                          txEvt in waitHndls)
                                    txEvt.Set();
                            }
                        }
                        finally { lock(locker) txEvnt.Set(); }
                    });
            waitHndls.Add(txEvnt);
        }
        util.WaitAll(waitHndls.ToArray());
        ThreadPool.SetMaxThreads(defaultMaxwrkrThreads, 
                                 defaultmaxIOThreads);

        lock (locker) if (X != null) throw X;
    }

3
2018-04-15 21:41



"साझा अपवाद चर (मुख्य धागे के लिए दृश्यमान)" क्या है? क्या होगा अगर कई अपवाद फेंक दिए जाते हैं? - MedicineMan
ऊपर नमूना कोड में, एक्स साझा अपवाद चर है ... यह वर्ग स्तर पर घोषित एक चर है, इसलिए यह कक्षा में सभी विधियों के बीच "साझा" है ... और जैसे ही पहला अपवाद फेंक दिया जाता है, है ना? थोड़े से रुकना चाहते हैं "? - Charles Bretana


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


1
2018-04-15 21:41