Soru ThreadPool.QueueUserWorkItem istisnalar nasıl yakalanır?


Bir istisna atar aşağıdaki kod var:

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

Eylem bir istisna atarken, programım çöküyor. Bu durumu ele almak için en iyi uygulama nedir?


İlgili: .Net ThreadPool Konularında İstisnalar


44
2018-04-15 21:37


Menşei


Bu soru ile hayatımı kurtardınız;) IIS'm çöküyordu ve sorunun ne olduğunu bilmiyordum ... Bu gibi bir problemdi: D - rpf


Cevaplar:


Eğer erişiminiz varsa actionKaynak kodu, bu yöntemde bir try / catch bloğu ekleyin; aksi halde yeni oluştur tryAction aramayı tamamlayan yöntem action Bir try / catch bloğunda.


24
2018-04-15 21:41





Bu şekilde try / catch ekleyebilirsiniz:

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

70
2018-04-15 21:43



Bir lambda serin kullanımı için +1. Bir iş parçacığı havuzundaki bir çalışan iş parçacığı web uygulamasında işlenmemiş bir özel durum attıysa, tüm web sunucusunun çökmesine neden olacağını buldum. Bu beni kurtardı! Teşekkürler! - CodingWithSpike
Örnek için +1 - CGK
+1 yaa maan! Bu tamamen harika bir ahbap! - ppumkin
Bu neden kabul edilen cevap değil? - TheAlbear


.Net 4.0 kullanıyorsanız, araştırmaya değer olabilir. Görev çünkü bunu sizin için halledebiliriz.

Orijinal kodunuzun karşılığı, ancak Görevler’i kullanmak

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

İstisnalarla başa çıkmak için, StartNew tarafından döndürülen Görev'e bir devam ekleyebilirsiniz. Şuna benzeyebilir:

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





Diğer iş parçacığı üzerinde, (yöntemi "sıraya alırken", bir try catch cümleciği ekleyin ... Sonra catch, özel bir özel durum değişkeni (ana iş parçacığına görünür) olarak yakalanmış özel durumu yerleştirin.

Daha sonra, ana iş parçacığınızda, tüm sıraya alınmış öğeler bittiğinde (bunun için bir bekletme kolu dizisi kullanın) Bazı iş parçacıklarının istisnayla paylaşılan bir istisnayı doldurup doldurmadığını kontrol edin ... Eğer yaptıysa, yeniden düzenleyin ya da uygun şekilde işleyin ...

İşte bunun için kullandığım son bir projeden bazı örnek kodlar ...
HasException, paylaşılan boolean ...

    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



"Paylaşılan özel durum değişkeni (ana iş parçacığına görünür") nedir? Birden çok istisna atılırsa ne olur? - MedicineMan
Yukarıdaki örnek kodda X, paylaşılan İstisna değişkenidir ... Sınıf düzeyinde bildirilen sadece bir değişken, yani sınıftaki tüm yöntemler arasında "paylaşılır" ... Ve ilk istisna atılır gelmez, siz değil mi? durdurmak ister misin? - Charles Bretana


Genelde yaptığım şey, action () yönteminin içinde büyük bir try ... catch bloğu oluşturmaktır. sonra özel bir değişken olarak istisnayı saklayın ve daha sonra ana iş parçacığının içinde ele alın


1
2018-04-15 21:41