Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从ThreadPool.QueueUserWorkItem捕获异常?_C#_.net_Multithreading_Threadpool - Fatal编程技术网

C# 如何从ThreadPool.QueueUserWorkItem捕获异常?

C# 如何从ThreadPool.QueueUserWorkItem捕获异常?,c#,.net,multithreading,threadpool,C#,.net,Multithreading,Threadpool,我有以下引发异常的代码: ThreadPool.QueueUserWorkItem(state => action()); 当操作抛出异常时,我的程序崩溃。处理这种情况的最佳做法是什么 相关:我通常做的是创建一个大的尝试。。。action()方法中的catch块 然后将异常存储为一个私有变量,然后在另一个线程的主线程内处理它(在“排队”的方法中,添加一个try-catch子句……然后在catch中,将捕获的异常放入一个共享异常变量(主线程可见) 然后,在主线程中,当所有排队的项目都完成

我有以下引发异常的代码:

ThreadPool.QueueUserWorkItem(state => action());
当操作抛出异常时,我的程序崩溃。处理这种情况的最佳做法是什么



相关:

我通常做的是创建一个大的尝试。。。action()方法中的catch块 然后将异常存储为一个私有变量,然后在另一个线程的主线程内处理它(在“排队”的方法中,添加一个try-catch子句……然后在catch中,将捕获的异常放入一个共享异常变量(主线程可见)

然后,在主线程中,当所有排队的项目都完成后(为此使用等待句柄数组),检查某个线程是否使用异常填充了该共享异常…如果是,请重新填充它或根据需要处理它

下面是我最近使用它的一个项目中的一些示例代码…
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;
    }
private void complete和queuepayloads(
IEnumerable有效负载,字符串进程ID)
{
List waitHndls=新列表();
int defaultMaxwrkrThreads,defaultmaxIOThreads;
GetMaxThreads(out defaultMaxwrkrThreads,
out defaultmaxIOThreads);
ThreadPool.SetMaxThreads(
MDMImportConfig.maxConcurrentIEUsageRequests,
defaultmaxIOThreads);
int qryNo=0;
foreach(有效载荷中的UsagePayload uPL)
{
ManualResetEvent txEvnt=新的ManualResetEvent(错误);
UsagePayload uPL1=uPL;
int qryNo1=++qryNo;
ThreadPool.QueueUserWorkItem(
代表
{
尝试
{
Thread.CurrentThread.Name=processId+
“+qryNo1;
如果(!HasException&!uPL1.IsComplete)
IEEDAL.GetPayloadReads(上传1,
processId,qryNo1);
如果(!HasException)
UsageCache.PersistPayload(uPL1);
如果(!HasException)
SavePayLoadToProcessQueueFolder(
uPL1,processId,qryNo1);
}
捕获(MeterUsageImportException iX)
{
log.Write(log.Level.Error,
“委托失败”iX.消息,iX);
锁(储物柜)
{
HasException=true;
X=iX;
foreach(手动重置事件
waitHndls中的txEvt)
txEvt.Set();
}
}
最后{lock(locker)txEvnt.Set();}
});
waitHndls.Add(txEvnt);
}
util.WaitAll(waitHndls.ToArray());
线程池.SetMaxThreads(默认MaxWrKrThreads,
defaultmaxIOThreads);
如果(X!=null)抛出X,则锁定(锁定器);
}

如果您有权访问
操作的源代码,请在该方法中插入一个try/catch块;否则,创建一个新的
tryAction
方法,将对
操作的调用封装在try/catch块中。

您可以这样添加try/catch:

        ThreadPool.QueueUserWorkItem(state =>
                                         {
                                             try
                                             {
                                                 action();
                                             }
                                             catch (Exception ex)
                                             {
                                                 OnException(ex);
                                             }
                                         });
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);

如果您使用的是.NET4.0,那么可能值得研究该类,因为它可以为您解决这个问题

与原始代码相同但使用任务的代码如下

Task.Factory.StartNew(state => action(), state);
要处理异常,您可以向StartNew返回的任务添加一个延续。它可能如下所示:

        ThreadPool.QueueUserWorkItem(state =>
                                         {
                                             try
                                             {
                                                 action();
                                             }
                                             catch (Exception ex)
                                             {
                                                 OnException(ex);
                                             }
                                         });
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);
简单代码:

public class Test
{
    private AutoResetEvent _eventWaitThread = new AutoResetEvent(false);

    private void Job()
    {
        Action act = () =>
        {
            try
            {
                // do work...
            }
            finally
            {
                _eventWaitThread.Set();
            }
        };
        ThreadPool.QueueUserWorkItem(x => act());
        _eventWaitThread.WaitOne(10 * 1000 * 60);
    }
}

什么是“共享异常变量(对主线程可见)”?如果抛出多个异常怎么办?在上面的示例代码中,X是共享异常变量…它只是在类级别声明的一个变量,所以它在类中的所有方法之间“共享”…一旦抛出第一个异常,您不想停止吗“?+1,非常酷地使用lambda。我发现如果线程池中的工作线程在我的web应用程序中抛出未经处理的异常,它将使整个web服务器崩溃。这救了我!谢谢!有了这个问题,你刚刚救了我的命;)我的IIS正在崩溃,我不知道是什么问题。。。这是一个问题:DU应该考虑使用任务。Task.RunwithErrorHandling的示例请参见