我有以下代码抛出异常:
ThreadPool.QueueUserWorkItem(state => action());
当操作抛出异常时,我的程序崩溃了。处理这种情况的最佳做法是什么?
答案 0 :(得分:70)
您可以像这样添加try / catch:
ThreadPool.QueueUserWorkItem(state =>
{
try
{
action();
}
catch (Exception ex)
{
OnException(ex);
}
});
答案 1 :(得分:24)
如果您有权访问action
的源代码,请在该方法中插入try / catch块;否则,创建一个新的tryAction
方法,该方法将对action
的调用包装在try / catch块中。
答案 2 :(得分:19)
如果您使用的是.Net 4.0,可能值得调查Task课程,因为它可以为您解决此问题。
相当于原始代码,但使用“任务”,似乎是
Task.Factory.StartNew(state => action(), state);
要处理异常,您可以为StartNew返回的Task添加延续。它可能看起来像这样:
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);
答案 3 :(得分:3)
在另一个线程上,(在你正在“排队”的方法中,添加一个try catch子句......然后在catch中,将捕获的异常放入一个共享的Exception变量中(主线程可见)。
然后在你的主线程中,当所有排队的项目都已完成时(为此使用一个等待句柄数组)检查某个线程是否填充了异常的共享异常......如果是,请重新抛出它或根据需要处理它。 ..
这是我最近用于...的项目的一些示例代码 HasException是共享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;
}
答案 4 :(得分:1)
我通常做的是在action()方法中创建一个很大的try ... catch块 然后将异常存储为私有变量,然后在主线程
中处理它答案 5 :(得分:0)
简单代码:
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);
}
}