0

I have a Windows service that spawns objects that do work. The objects have two methods that get kicked off as Tasks. During housekeeping or shutdown, I call a Stop method on the object that tell the Tasks to stop. I have a list of the Tasks created for the objects' methods, so I do a Task.WaitAll for them. But, I'm getting a NullReferenceException during shutdown. I thought one of the Task objects was null, so I tested for it with a .Where(pt => pt != null).ToArray(), but that didn't work.

Here's a snippet:

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:

I think that the Task is not null, but that the original processor object is null. But, I'm not sure how to check that or prevent this. I'm new to Tasks, so I'm still getting my head around it.

Thoughts?

Full Error Message:

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()<---
5
  • Does the NullReferenceException show the line that's failing? Can you reproduce this in a short but complete program? Commented Aug 12, 2014 at 21:02
  • please get the call stack information of System.NullReferenceException Commented Aug 12, 2014 at 21:06
  • Also, generally use Task.Run instead of Task.Factory.StartNew Commented Aug 12, 2014 at 21:10
  • Task.WaitAll here is a good reference link Commented Aug 12, 2014 at 21:11
  • There don't seem to be any line references. I'm wondering if I need to removed tasks associated with the original object from the collection when I remove the object from its collection. Commented Aug 12, 2014 at 21:29

2 Answers 2

2

As explained at the documentation linked by DJ KRAZE, the AggregateException means that the NullReferenceException was thrown by one of the tasks (not that the processorTasks collection is null, nor one of its items, as that would produce an ArgumentNullException)

Check the callstack of the NullReferenceException (which would be found at the AggregateException.InnerExceptions property), or simply set your debugger to break on thrown NullReferenceExceptions, in order to find the actual exception.

Sign up to request clarification or add additional context in comments.

1 Comment

Should I keep my task objects in a dictionary or something so that I can remove them when I remove my processor object?
0

Ok, here's what I went with. It seems to be working as I want and it is testing well.

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

When new work is received:

// 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);

When the service shuts down, it does this:

// 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());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.