Reputation: 55
I'm using ThreadPool
with generic repository and I'm getting this error;
'Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.'
private readonly AuthorizedServiceService _authorizedServiceService;
private readonly CustomerService _customerService;
public IConfigurationRoot Configuration { get; }
public UpdateService(AuthorizedServiceService authorizedServiceService, CustomerService customerService)
{
_authorizedServiceService = authorizedServiceService;
_customerService = customerService;
}
public void UpdateAllRecords()
{
_authorizedServiceService.GetByActive().ToList().ForEach(UpdateAuthorizedServiceRecords);
}
void UpdateAuthorizedServiceRecords(AuthorizedService authorizedService)
{
//UpdateStart(authorizedService);
var mywatch = new Stopwatch();
mywatch.Start();
ThreadPool.QueueUserWorkItem(new WaitCallback(state => { UpdateStart(authorizedService); }));
mywatch.Stop();
mywatch.Reset();
}
public void UpdateStart(AuthorizedService authorizedService)
{
UpdateCustomers(authorizedService);
ThreadPool.QueueUserWorkItem(new WaitCallback(state => { UpdateCustomers(authorizedService); }));
}
internal void UpdateCustomers(AuthorizedService authorizedService)
{
try
{
if (authorizedService.CustomerUpdateLocked)
return;
var carDatabaseClient = new DataCarDatabaseClient();
var result = carDatabaseClient.GetCustomers(authorizedService, authorizedService.LastCustomerUpdate);
var dataRows = Convert<Customer>(result).Select(s=>
{
s.Id = authorizedService.Code + "-" + s.DcId;
s.AuthorizedService = authorizedService;
return s;
}).ToList();
_customerService.SaveOrUpdate(dataRows.OrderBy(p=>p.Id).FirstOrDefault(),p=> p.Id != null);
}
catch (Exception e)
{
// ignored
}
}
Generic Repository Method;
public void AddOrUpdate(T entity, Expression<Func<T, bool>> predicate)
{
var exists = predicate != null ? Context.Set<T>().Any(predicate) : Context.Set<T>().Any();
if (!exists)
Context.Set<T>().Add(entity);
else
Context.Set<T>().Update(entity);
Context.SaveChanges();
}
Upvotes: 3
Views: 13071
Reputation: 9165
It happens because all dependencies in the main thread are disposed when its execution finishes and you're trying to access them in another thread. To deal with this situation you need to create a scope in your background thread and resolve AuthorizedServiceService
there:
private readonly IServiceScopeFactory _scopeFactory;
public UpdateService(AuthorizedServiceService authorizedServiceService, CustomerService customerService, IServiceScopeFactory scopeFactory)
{
_authorizedServiceService = authorizedServiceService;
_customerService = customerService;
_scopeFactory = scopeFactory;
}
public void UpdateStart(AuthorizedService authorizedService)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(state => {
using (scope = _scopeFactory.CreateScope())
{
var scopedAuthorizedService = scope.ServiceProvider.GetService(typeof(AuthorizedServiceService));
UpdateCustomers(scopedAuthorizedService); }));
}
}
Upvotes: 9