How to catch exceptions from a ThreadPool.QueueUserWorkItem?

后端 未结 6 1827
借酒劲吻你
借酒劲吻你 2020-12-01 07:19

I have the following code that throws an exception:

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

When the action throws an exception

6条回答
  •  猫巷女王i
    2020-12-01 08:00

    On the other thread, (in the method you are "queueing" up, add a try catch clause... .Then in the catch, place the caught exception into a shared Exception variable (visible to the main thread).

    Then in your main thread, when all queued items have finished (use a wait handle array for this) Check if some thread populated that shared exception with an exception... If it did, rethrow it or handle it as appropriate...

    here's some sample code from a recent project I used this for...
    HasException is shared boolean...

        private void CompleteAndQueuePayLoads(
               IEnumerable payLoads, string processId)
        {
            List waitHndls = new List();
            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;
        }
    

提交回复
热议问题