W
WRBehning
Guest
I have the need to launch different implementations of our IBusinessLogic interface an different threads.
This is being designed in .Net Core3.0 as a console application.
I use Unity to deliver the concrete instance of the BusinessLogic, then pass that to a BackgroundWorker. This seems to work as expected.
The problem I am having is that the application exits all threads at a certain point (It is related to EF Core), but no exceptions are thrown, and I can't find any indication as to what the issue is.
When the businesslogic is executed under the same thread - no Backgroundworker -, it all works as exptected.
Any suggestions?
Here is the relevent code :
See the ProcessBusinessLogic method
public class Main : IDisposable
{
private IUnityContainer _container;
public Main()
{
// Get settings from appsettings
var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
var configuration = builder.Build();
var connectionString = configuration.GetConnectionString("MyDatabaseConnection");
// Add the Interception extension
_container.AddNewExtension<Interception>();
_container = new UnityContainer();
// Register Logger
// Register Repository
_container.RegisterType<IRepository, MyRepository>(new TransientLifetimeManager()
, new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<LoggingAspect>());
// Register Data Provider
_container.RegisterType<IDataProvider, MyDataProvider>(new TransientLifetimeManager()
, new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<LoggingAspect>()
, new InjectionConstructor(connectionString));
// Register Business Logic
_container.RegisterTypes(AllClasses.FromLoadedAssemblies()
.Where(type => typeof(IBusinessLogic).IsAssignableFrom(type))
.Where(t => !t.IsGenericTypeDefinition)
, WithMappings.FromAllInterfaces
, WithName.TypeName
, WithLifetime.Transient
, c => new InjectionMember[] { new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<LoggingAspect>() }
);
var salesPadRepository = _container.Resolve<IExptSalesPadRepository>();
_loaderProcessList = salesPadRepository.GetLoaderProcesses();
}
public bool ProcessBusinessLogic()
{
foreach (var loaderProcessDto in _loaderProcessList.Where(o => o.BusinessLogic.Equals("XYZ")))
{
var businessLogicName = string.Concat(loaderProcessDto.BusinessLogic, "BusinessLogic");
var businessLogic = _container.Resolve<IBusinessLogic>(businessLogicName);
// When running on BW - EF Core will kill thread - app just quits with no exceptions being thrown
var executeProcessBackgroundWorker = new BackgroundWorker();
executeProcessBackgroundWorker.DoWork += ExecuteProcess_DoWork;
executeProcessBackgroundWorker.RunWorkerCompleted += ExecuteProcess_RunWorkerCompleted;
executeProcessBackgroundWorker.RunWorkerAsync(businessLogic);
// Running on the same thread, all works as exptected
//var dwe = new DoWorkEventArgs(businessLogic);
//ExecuteProcess_DoWork(this, dwe);
}
return true;
}
private void ExecuteProcess_DoWork(object sender, DoWorkEventArgs e)
{
var businessLogic = e.Argument as IBusinessLogic;
// Create the Order Data
businessLogic.CreateLoaderData(@"C:\Temp\InputData.txt");
// Preprocess data
businessLogic.ProcessLoaderData();
// Process the Input Data
businessLogic.ProcessInput();
}
private void ExecuteProcess_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
var x = e;
// Just a sanity check at this point
}
}
}
EF Core DataProvider:
See the Create method:
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using MyRepository.Configurations;
using System;
using System.Linq;
using System.Text;
namespace MyRepository.DataProvider
{
public class MyDataProvider : DbContext, IMyDataProvider
{
public string DataProviderMessage { get; private set; }
public MyDataProvider(string connectionString)
: base(new DbContextOptionsBuilder().UseSqlServer(connectionString).Options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new LoaderProcessConfiguration());
}
public new DbSet<TModel> Set<TModel>() where TModel : class
{
ChangeTracker.DetectChanges();
return base.Set<TModel>();
}
public IQueryable<TModel> GetTable<TModel>() where TModel : class
{
return Set<TModel>();
}
public TModel Create<TModel>() where TModel : class
{
var model = Activator.CreateInstance<TModel>();
var x = Set<TModel>();
// The next line will kill all threads when running under BW worker
x.Add(model);
return model;
}
public EntityEntry GetEntityStates<TModel>(TModel model) where TModel : class
{
var entityState = Entry(model);
return entityState;
}
}
}
Bill Behning
Continue reading...
This is being designed in .Net Core3.0 as a console application.
I use Unity to deliver the concrete instance of the BusinessLogic, then pass that to a BackgroundWorker. This seems to work as expected.
The problem I am having is that the application exits all threads at a certain point (It is related to EF Core), but no exceptions are thrown, and I can't find any indication as to what the issue is.
When the businesslogic is executed under the same thread - no Backgroundworker -, it all works as exptected.
Any suggestions?
Here is the relevent code :
See the ProcessBusinessLogic method
public class Main : IDisposable
{
private IUnityContainer _container;
public Main()
{
// Get settings from appsettings
var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
var configuration = builder.Build();
var connectionString = configuration.GetConnectionString("MyDatabaseConnection");
// Add the Interception extension
_container.AddNewExtension<Interception>();
_container = new UnityContainer();
// Register Logger
// Register Repository
_container.RegisterType<IRepository, MyRepository>(new TransientLifetimeManager()
, new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<LoggingAspect>());
// Register Data Provider
_container.RegisterType<IDataProvider, MyDataProvider>(new TransientLifetimeManager()
, new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<LoggingAspect>()
, new InjectionConstructor(connectionString));
// Register Business Logic
_container.RegisterTypes(AllClasses.FromLoadedAssemblies()
.Where(type => typeof(IBusinessLogic).IsAssignableFrom(type))
.Where(t => !t.IsGenericTypeDefinition)
, WithMappings.FromAllInterfaces
, WithName.TypeName
, WithLifetime.Transient
, c => new InjectionMember[] { new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<LoggingAspect>() }
);
var salesPadRepository = _container.Resolve<IExptSalesPadRepository>();
_loaderProcessList = salesPadRepository.GetLoaderProcesses();
}
public bool ProcessBusinessLogic()
{
foreach (var loaderProcessDto in _loaderProcessList.Where(o => o.BusinessLogic.Equals("XYZ")))
{
var businessLogicName = string.Concat(loaderProcessDto.BusinessLogic, "BusinessLogic");
var businessLogic = _container.Resolve<IBusinessLogic>(businessLogicName);
// When running on BW - EF Core will kill thread - app just quits with no exceptions being thrown
var executeProcessBackgroundWorker = new BackgroundWorker();
executeProcessBackgroundWorker.DoWork += ExecuteProcess_DoWork;
executeProcessBackgroundWorker.RunWorkerCompleted += ExecuteProcess_RunWorkerCompleted;
executeProcessBackgroundWorker.RunWorkerAsync(businessLogic);
// Running on the same thread, all works as exptected
//var dwe = new DoWorkEventArgs(businessLogic);
//ExecuteProcess_DoWork(this, dwe);
}
return true;
}
private void ExecuteProcess_DoWork(object sender, DoWorkEventArgs e)
{
var businessLogic = e.Argument as IBusinessLogic;
// Create the Order Data
businessLogic.CreateLoaderData(@"C:\Temp\InputData.txt");
// Preprocess data
businessLogic.ProcessLoaderData();
// Process the Input Data
businessLogic.ProcessInput();
}
private void ExecuteProcess_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
var x = e;
// Just a sanity check at this point
}
}
}
EF Core DataProvider:
See the Create method:
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using MyRepository.Configurations;
using System;
using System.Linq;
using System.Text;
namespace MyRepository.DataProvider
{
public class MyDataProvider : DbContext, IMyDataProvider
{
public string DataProviderMessage { get; private set; }
public MyDataProvider(string connectionString)
: base(new DbContextOptionsBuilder().UseSqlServer(connectionString).Options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new LoaderProcessConfiguration());
}
public new DbSet<TModel> Set<TModel>() where TModel : class
{
ChangeTracker.DetectChanges();
return base.Set<TModel>();
}
public IQueryable<TModel> GetTable<TModel>() where TModel : class
{
return Set<TModel>();
}
public TModel Create<TModel>() where TModel : class
{
var model = Activator.CreateInstance<TModel>();
var x = Set<TModel>();
// The next line will kill all threads when running under BW worker
x.Add(model);
return model;
}
public EntityEntry GetEntityStates<TModel>(TModel model) where TModel : class
{
var entityState = Entry(model);
return entityState;
}
}
}
Bill Behning
Continue reading...