Reputation: 148524
My Startup.cs
file is :
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddHttpContextAccessor();
services.AddScoped<IFoo,Foo>(); // Notice Scoped service
}
Please notice that IFoo
is a scoped service.
IFoo
is a simple service :
public interface IFoo
{
public int Get(int id)
{
return id;
}
}
public class Foo : IFoo
{
}
And here is the simple contoller :
public class WeatherForecastController : ControllerBase
{
private readonly IHttpContextAccessor _accessor;
private readonly IFoo _fooService;
public WeatherForecastController(IFoo fooService, IHttpContextAccessor accessor)
{
_fooService = fooService;
_accessor = accessor;
}
[HttpGet]
public async Task<int[]> Get()
{
async Task Foo()
{
try
{
await Task.Delay(4000);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Console.WriteLine("***Service******" + _fooService.Get(4));
}
catch (Exception e)
{
Console.Write(e);
}
}
Foo(); // non awaitable
return new[] { 0 };
}
}
Please notice that Foo()
is without await
.
Now, When I run the code , I DO see the result of the scoped service being accessed after the request has completed ( since Foo
is not awaited) :
I was expecting to see Null reference exception since it's a scoped service that is executed a long time after the main request thread has executed.
MSDN :
Why am I not getting a null reference exception?
Scoped service is only per request. and the request has finished long time before it was accessed by the task.
Upvotes: 2
Views: 437
Reputation: 9221
Scoped services are disposed when the scope is disposed, that doesn't mean that all references to scoped services become null. That means that the scope calls Dispose() method on all disposable objects that are created inside the scope. When you call a method on an object that has been disposed the object should raise ObjectDisposedException
, you should not get NullReferenceException
.
Try with the following and you will see that ObjectDisposedException
is thrown:
public interface IFoo
{
public int Get(int id)
{
return id;
}
}
public class Foo: IFoo, IDisposable
{
public bool IsDisposed { get; private set; }
public void Dispose()
{
if (!IsDisposed)
{
IsDisposed = true;
}
}
private void CheckDisposed()
{
if (IsDisposed) throw new ObjectDisposedException(nameof(Foo));
}
public int Get(int id)
{
CheckDisposed();
return id;
}
}
Upvotes: 1