Visual Studio Code Analysis generates the warning "Dispose objects before losing scope" (CA2000) on the monitor
variable in this method.
private void MonitorJob(IJob job, CancellationToken cancellationToken)
{
var monitor = new JobMonitor(job, _backend); // <- CA2000
try
{
var task = monitor.Run(cancellationToken);
_activeJobs[task] = monitor;
}
catch
{
monitor.Dispose();
throw;
}
}
I understand what CA2000 does, and I'm usually able to work out why my code violates the rule and make the appropriate changes.
In this case, however, I'm stumped - is this really a false positive, or am I missing something?
Using Visual Studio 2015 Enterprise Edition, targeting .NET 4.5, using C# 6.
You could leak this disposable if an exception is thrown here:
private void MonitorJob(IJob job, CancellationToken cancellationToken)
{
var monitor = new JobMonitor(job, _backend);
// <- Exception
try
{
var task = monitor.Run(cancellationToken);
_activeJobs[task] = monitor;
}
catch
{
monitor.Dispose();
throw;
}
}
This could be caused by say a ThreadAbortException
or any other exception that's injected into a thread by the runtime. I'd suggest declaring the variable outside of the try
block but assign it within. Also, set it to null
on successfully assigning it to _activeJobs
.
private void MonitorJob(IJob job, CancellationToken cancellationToken)
{
JobMonitor monitor;
try
{
monitor = new JobMonitor(job, _backend);
var task = monitor.Run(cancellationToken);
_activeJobs[task] = monitor;
monitor = null;
}
finally
{
if(monitor!=null)
{
monitor.Dispose();
}
throw;
}
}
Even then though, it may not be enough to shut up the warning, at which point I'd suggest adding a suppression for it.
I assume that _activeJobs[task] = monitor;
is a simple assignment and doesn't throw exception. If so separate storing monitor from creating monitor.
private void MonitorJob(IJob job, CancellationToken cancellationToken)
{
Task task;
var monitor = CreateJobMonitor(job, _backend, out task);
_activeJobs[task] = monitor;
}
private JobMonitor CreateJobMonitor(IJob job, CancellationToken cancellationToken, out Task task)
{
var monitor = new JobMonitor(job, _backend);
try
{
task = monitor.Run(cancellationToken);
return monitor;
}
catch
{
monitor.Dispose();
throw;
}
This way, CreateJobMonitor means either returning a valid object or throwing exception. There is no chance to return disposed object reference.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.