使用Task.WaitAll时的NullReference

时间:2014-08-12 21:00:56

标签: c#

我有一个Windows服务,可以生成有效的对象。这些对象有两种方法可以作为任务启动。在内务或关机期间,我在对象上调用一个告诉任务停止的Stop方法。我有一个为对象创建的任务列表'方法,所以我为他们做了一个Task.WaitAll。但是,我在关机期间收到NullReferenceException。我认为其中一个Task对象是null,所以我用.Where(pt => pt!= null).ToArray()测试它,但是没有用。

这是一个片段:

var peProcessor = new PrintExpertProcessor(runId);
processorTasks.Add(Task.Factory.StartNew(() => peProcessor.ProcessRun()));
processorTasks.Add(Task.Factory.StartNew(() => peProcessor.StartMonitor()));
processors.Add(peProcessor);
// Later in the code
Task.WaitAll(processorTasks.ToArray()); // System.AggregateException: System.NullReferenceException:

我认为Task不是null,而是原始处理器对象为null。但是,我不确定如何检查或阻止这种情况。我是对“任务”的新手,所以我仍然不知所措。

思想?

完整错误消息:

System.AggregateException: System.NullReferenceException: Object reference not set to an instance of an object.
   at WOW.PrintExpert.AwdProcessor.Code.PrintExpertProcessor.StopProcessor()
   at WOW.PrintExpert.AwdProcessor.Code.PrintExpertProcessor.ProcessRun()
   at System.Threading.Tasks.Task.Execute()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.WaitAll(Task[] tasks, Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at WOW.PrintExpert.AwdProcessorService.ProcessorService.OnStop()
---> (Inner Exception #0) System.NullReferenceException: Object reference not set to an instance of an object.
   at WOW.PrintExpert.AwdProcessor.Code.PrintExpertProcessor.StopProcessor()
   at WOW.PrintExpert.AwdProcessor.Code.PrintExpertProcessor.ProcessRun()
   at System.Threading.Tasks.Task.Execute()<---

2 个答案:

答案 0 :(得分:2)

正如DJ KRAZE链接的文档中所解释的那样,AggregateException意味着其中一个任务抛出了NullReferenceException(并不是因为processorTasks集合是null,也不是它的一个项目,因为它会产生一个ArgumentNullException

检查NullReferenceException的调用堆栈(可以在AggregateException.InnerExceptions属性中找到),或者只是将调试器设置为在抛出的NullReferenceException上中断,以便找到实际的异常。

答案 1 :(得分:0)

好的,这就是我的用途。它看起来像我想要的那样正常运行。

// Service class
private Dictionary<int, Task> processorMonitorTasks = new Dictionary<int, Task>();
private Dictionary<int, Task> processorTasks = new Dictionary<int, Task>();

收到新作品时:

// Spawn new processor object
var peProcessor = new PrintExpertProcessor(runId);

// Create tasks for the processors methods
processorTasks.Add(runId, Task.Run(() => peProcessor.ProcessRun()));
processorMonitorTasks.Add(runId, Task.Run(() => peProcessor.StartMonitor()));

// Add the processor the collection
processors.Add(peProcessor);

当服务关闭时,它会执行以下操作:

// Copying the object references to a new list prevents enumeration changed exceptions.
foreach (var proc in processors.ToList())
{
    if (proc != null && !proc.IsStopped)
    {
        // Direct that each object come to a stop
        proc.StopProcessor();
    }
}

// Now, wait for each one to stop.
Task.WaitAll(processorTasks.Values.ToArray());
Task.WaitAll(processorMonitorTasks.Values.ToArray());