NamedScopes Ninject bindings and async (threading) - c#

My project is structured by services and repositories (all repositories share the db context). In one of my service layers, I have an asynchronous method that writes to the database using a repository. The web request will finish and dispose of the context before this method can get to use it. I tried to understand NamedScopes as stated in this answer. I still can't seem to understand how to implement it. I'll show how my project is structured and hope someone can help me at the code level.
Bindings
private static void RegisterServices(IKernel kernel)
{
//dbcontext
kernel.Bind<EntityDatabaseContext>().ToMethod(context => new EntityDatabaseContext()).InRequestScope();
//unit of work
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
//repositories
kernel.Bind<IRepository<Account>>().To<Repository<Account>>().InRequestScope();
//services
kernel.Bind<IAuthenticationService>().To<AuthenticationService>().InRequestScope();
}
AuthenticationService uses constructor injection
public AuthenticationService(UnitOfWork unitOfWork, IRepository<Account> accountRepository){}
A method inside my AuthenticationService
//this is a background process
public Task SomeMethodAsync(string text)
{
//spin it off into a new task
return Task.Factory.StartNew(() => SomeMethod(text));
}
SomeMethod makes use of accountRepository. Please tell me if anymore information is needed. Please help me with the threading issue, if NamedScopes is the solution, how do I implement it in my case?
Basically, a background process is being executed and it is using a context that is being disposed of by ninject due to the request scope.

You should be aware that running background threads can cause you many problems. IIS can decide to recycle the app pool at any time which will terminate your thread immediately (or it doesn't execute in some cases at all) leaving your application in an inconsistent state.
http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx
The easiest and least error prone wayto run asyncronous operations is to implement a windows service and delegate those async operations to the windows service e.g. using MSMQ.
If you still want to go the hard way then read about HostingEnvironment.RegisterObject and IRegisteredObject to prevent these inconsistent situations.
The Ninject part is quite easy. Just create some job processor class e.g. MyJobProcessor taking all required dependencies to execute the task. It should implement INotifyWhenDisposed. The easiest way to do so is to derive from DisposeNotifyingObject.
public class MyJobProcessor : DisposeNotifyingObject, IRegisteredObject
{
public void Execute() { ... }
public void Stop(bool immediate) { ... }
}
Inject this processor to the controller and let the Task start it and dispose it when it has finished its work.
Task.Factory.StartNew(() =>
{
try
{
processor.Execute();
}
finally
{
processor.Dispose);
}
});
Specify that it is the scope for its dependencies.
Bind<MyJobProcessor>().ToSelf().Named("MyJobProcessor").DefinesNamedScope("MyJobProcessorScope");
Bind<IUnitOfWork>().To<UnitOfWork>().WhenAnyAnchestorNamed("MyJobProcessor").InNamedScope("MyJobProcessorScope");

Related

Why StructureMap container doesn't return the control then calling GetInstance?

I have following registration of the service:
For<Internal.FullPdfExporter>().Use<Internal.FullPdfExporter>();
I have a exporter factory to create different exporters. First of all injected StructureMap container to this factory:
private readonly IContainer _container;
public ExporterFactory(IContainer container)
{
_container = container;
}
Then i use following code to get a instance of FullPdfExporter:
private IExporterBase CreateInstance(Type exporterType)
{
return _container.GetInstance(exporterType) as IExporterBase ;
}
But this code doesn't return control at all. What's the problem is here?
I tried to check all registered instances in debug, and notices that container has registration for "Internal.FullPdfExporter".
Note: Internal is a alias for namespace;
How i get exporter from factory (code of business service which is called from Http Controller):
var task = Task.Run(async () =>
{
foreach (var item in exportData.OrderBy(x => x.ExportUid))
{
var exporter = _exporterFactory.GetBookExporter(param1, param2);
await exporter.StartExport(item.ExportUid);
if (!exporter.IsCompletedSuccessfully)
{
break;
}
}
});
return response;
Note: If to place _exporterFactory.GetBookExporter call before the task.Run, everything works good. Container is able to resolve the dependency.
Code of the GetBookExporter method:
public IExporterBase GetBookExporter(BookSchema bookSchema, PublishProfileType publishProfileType)
{
return CreateInstance(typeof(Internal.FullPdfExporter));
}
Your general logic is flawed. You expect things to run, even after your http call is already over.
Once you return a response, things happen in the ASP.NET framework.
Dependency injection containers finish their scope, objects get disposed.
Keeping those references that are probably scoped or transient in nature until after the call has completed is not going to work. Granted, sometimes it might work, when you have classes that do not implement IDisposable or you just get lucky with a microsocond timing, but generally speaking, this is not anticipated and not meant to work.
If you want to do work after sending out the reply, you have to hand this work over to another party. Maybe you save it into a database and another service picks it up and works on it. Or maybe you have another program or thread running and you try some IPC. But you should not expect threads or tasks referencing things from the scope of your http call to work after it's done.

Best approach to a class that would run in background polling other API and saving data

So I have a website written in .NET Core C# and I would like to run a process in the background that would make API calls to other website and save the data in database.
I have created ApiAccessor class and would like to invoke the method from the controller (which uses dependency injections for it's database connection), but if I pass them to the ApiAccessor (it would be async) the connection is already disposed of. I've tried injecting it from the get go, but it will still say that the interfaces are disposed, by the time it finishes. I can only do await on it, but this would cause user to wait for too long. What approach should I take with this one? I am a newbie at DI. Maybe some Singleton class? I would still don't know how to pass dependency injections to singleton
ApiAccessor:
IUserAccount _userAccounts;
public ApiAccessor(IConfiguration configuration, IUserAccount userAccounts)
{
_configuration = configuration;
_userAccounts = userAccounts;
}
//...
MethodToPollApi(){
var newUserIdToAdd = // just some kind of new data from api
_userAccounts.Add(newUserIdToAdd) // accessing DB, that causes errors
}
Controller:
void Index(){
MethodToPollApi();
return View();
}
I would consider an idea of using as called background jobs. There are a few popular frameworks for this type of solutions. Within them: custom implementation based on IHostedService, Quartz.NET, Hangfire, and many more available.
I used to play with many of them, personally prefer Hangfire as it self bootstrapped, provide nice UI for jobs dashboard, and really easy to use - for instance, that is how triggering jobs light look like with it:
Run once immediately:
var jobId = BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget!"));
Run delayed:
BackgroundJob.Schedule(() => Console.WriteLine("Delayed!"), TimeSpan.FromDays(7));
Run repeating:
var jobId = RecurringJob.AddOrUpdate(() => Console.WriteLine("Recurring!"), Cron.Daily);
Pick up completed job and continue:
BackgroundJob.ContinueWith(jobId, () => Console.WriteLine("Continuation!"));
Continuing the answer from #Dmitry. With Hangfire you can do something like this.
services.AddHangfire(x => x.UseSqlServerStorage("<Your connection string>"));
Hope this helps.

When to compose application root in a windows service

Given a C# console application that will run as a windows service, there are sort of 2 application entry points. The first obvious one is the static void Main method. Part of the job of this method is to install something that extends ServiceBase and then run it to get its OnStart method to be invoked. There are also higher level tools like Topshelf that help you avoid lower level ServiceBase implementations, but still, you end up with 2 potential application entry points: static void Main, and some kind of OnStart method.
Should the application root for such a service be composed within the service's OnStart method, or earlier than that as part of static void Main?
It seems that there could be an advantage to composing within the service's OnStart method (and destroying / disposing it in the OnStop method) since restarting a service would then compose a new application root. The only real disadvantage I can see here is that if I am using a tool like Topshelf, I can't use the DI container to obtain an instance of my Service class. Then again, that's probably not a real disadvantage. Still, most of the applications I read compose the root during Main, not during OnStart, and I'm not sure why.
Is one approach really better than the other, or does it depend, and my question is really an opinion-based one?
I think it's more an opinion than a fact, but I prefer to compose during service building and then use OnStart() to activate the service I composed before. This is the way I usually work (with Topshelf). For example:
program.cs
public class Program
{
private static ILifetimeScope _scope;
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
public static void Main(string[] args)
{
try
{
XmlConfigurator.Configure();
// configure composition
_scope = CompositionRoot.CreateScope();
HostFactory.Run(x =>
{
x.UseLog4Net();
x.UseAutofacContainer(_scope);
x.Service<IMyService>(svc =>
{
svc.ConstructUsingAutofacContainer();
svc.WhenStarted(tc => tc.Start());
svc.WhenStopped(tc =>
{
tc.Stop();
_scope.Dispose();
});
});
x.RunAsNetworkService();
x.StartManually();
});
}
catch (Exception e)
{
Log.Error("An error occurred during service construction.", e);
throw;
}
}
}
composition.cs
internal class CompositionRoot
{
public static ILifetimeScope CreateScope()
{
var builder = new ContainerBuilder();
builder.RegisterType<MyService>().As<IMyService>().SingleInstance();
// other things you want to register
return builder.Build();
}
}
imyservice.cs
public interface IMyService
{
void Start();
void Stop();
}
The only real disadvantage I can see here is that if I am using a tool like Topshelf, I can't use the DI container to obtain an instance of my Service class
This is true, but you don't need to access the program.cs code, just the MyService code, which will represent the actual "core" code of your service.
Also when you stop the service you will actually kill it (unless you pause it), so the composition will be executed again, no matter if you put it inside the "onStart()" or not.
As usual, IMHO. :)

How to transfer DI requestscope to an other thread?

Context:
I am using DI in my Web application. (I am using NInject, but hopefully this should not matter)
Some places constructor injection is not possible, for example in my custom log4net database logger (that's not me, who instantiates my custom logger instead the log4net framework). So I am using my DI container there in service locator DP mode, and asking an instance resolve explicitly in the logger code.
Note this is just a sample, in many other cases I had to use NInject as service locator DP instead of constructor injection.
Now the problem:
I have an IAuditContextProvider which serves current request's audit data, like IP etc. The question arises how I configure my DI container to instantiate a concrete provider. So far I've used a request scope (singleton by request) what is supported out of box by NInject.
However recently I faced the fact I had to start a background processing initiated by a request. This is done by
// This is 'outside' it's actually a request serving method running in the request context, btw it is an MVC action method,
// Pseudo code:
var auditProvider = Locator.Resolve<IAuditProvider>()
Task.Run(() =>
{
// I would like to get the very same resolved auditProvider instance here as outside.
// Please note: outer local variables are not solution, because of implicit calls here inside, for example if there is a logging statement here, then the service locator in the custom logger must resolve the very same instance as outside
// Some how I must 'stamp' this thread to be the 'same' as the outside
// request thread in point of view of my custom scope resolver (see below)
}
Note: Configuring the DI container a wide scoped singleton are not solution because of multiple requests are server parallel, and they can not use a common auditProvider.
OK, I thought this is what for custom (resolving) scopes are for. Here is the pseudo code how I am configuring my DI container:
kernel
.Bind(typeof(IAuditContextProvider))
.To(typeof(WebAuditContextProvider)).InScope(dummy =>
{
// Here I have to return a very same object/number/id when in
// 'outside' the request thread, and inside the worker thread.
// This way I hopefully get the very same instance when resolving.
// To be short: I have no idea how?
});
I don't think there is a good answer for your question within the current bounds.
I do have an alternative suggestion - just perform the work synchronously in another process. This would require a form of inter-process communication (IPC) but shouldn't be too difficult.
A simple but effective form of IPC is just writing a record to a database table (acting like a queue) and having a windows service/daemon polling for new records to "process". In this example, you would put a record in the table with the contextual information (user id, etc) and the service would utilize this context to perform the work synchronously, but the workflow would be asynchronous to the Web UI.
This also has a nice side benefit: You can start to build monitoring, retry logic, etc into the service. These things are much harder to do reliably within an ASP.NET model.
You could forgo the database queue completely by using something like message queues/buses/events, but the basic concept is the same.
Update:
Did you try to use closures in C#? Like this:
var auditProvider = Locator.Resolve<IAuditProvider>()
Task.Run(() =>
{
// with closure you'll get that very variable you need:
auditProvider.SomeMethod();
}
You should read whole article about closures by John Skeet and how they can help you together with TPL.
Other useful information:
Such DI is being called as Ambient Context in famous book Dependency Injection by M. Seeman:
A truly universal CROSS-CUTTING CONCERN can potentially pollute a large part of the API for an application if you have to pass an instance around to every collaborator. An alternative is to define a context that’s available to anyone who needs it and that can be ignored by everyone else.
The AMBIENT CONTEXT is available to any consumer via a static property
or method. A consuming class might use it like this:
public string GetMessage() { return SomeContext.Current.SomeValue; }
In this case, the context has a static Current property that a consumer can access. This property may be truly static, or may be associated with the currently executing thread. To be useful in DI scenarios, the context itself must be an ABSTRACTION and it must be possible to modify the context from the outside—in the previous example, this means that the Current property must be writable. The context itself might be implemented as shown in the following listing.
The context is an abstract class, which allows us to replace one context with another implementation at runtime.
public abstract class SomeContext
{
public static SomeContext Current
{
get
{
// Get current context from TLS
var ctx = Thread.GetData(Thread.GetNamedDataSlot("SomeContext")) as SomeContext;
if (ctx == null)
{
ctx = SomeContext.Default;
Thread.SetData(Thread.GetNamedDataSlot("SomeContext"), ctx);
}
return ctx;
}
set
{
Thread.SetData(Thread.GetNamedDataSlot("SomeContext"), value);
}
}
public static SomeContext Default = new DefaultContext();
public abstract string SomeValue { get; }
}
TLS here stands for Thread Local Storage, which can be useful idea for you here.
Also I suggest you to read about OperationContext class, which can be helpful for you if you want to pass some context for your Task, something like this:
// save current context before task start
var operationContext = OperationContext.Current;
Task.Run(() =>
{
// set current operation context inside your Task with closure
OperationContext.Current = operationContext;
// Your work here
}

In a Windows Service using Castle.Windsor and the Task Parallels Library, what is the appropriate Lifestyle and release process?

I'm writing a task-execution engine and I'm running into some questions about what is the appropriate way to insure that everything is properly released when I'm using Castle.Windsor (ver 2.5.1.0) in a Task-Parallels-Library system.
I've included a highly simplified pseudo-code example of what I'm doing at the end of the post.
Here are my questions
Castle.Windsor does not have a "PerTask" lifestyle and given the way the TPL uses threads, I believe the PerThread lifestyle won't work. So what is the appropriate lifestyle?
If I force TPL to be a Task-Per-Thread mechanism, it's my understanding that calling Release on a PerThread lifestyle won't actually release anything until the container is disposed of, and currently I only have a single container that lives forever. Is there a better way to set up my containers to support PerThread?
In the example below, I've also indicated three potential places where I can call release on the container. According to most of what I've read, I should rarely need to call release myself, but if I don't call it at those places, how do those registrations get disposed of?
The Service:
class Service : ServiceBase
{
IWindsorContainer _container;
Engine _engine;
public Service()
{
_container = new WindsorContainer();
_container.Register(Component.For<Engine>().ImplementedBy<Engine>().LifeStyle.Singleton);
_container.Register(Component.For<ISession>().UsingFactoryMethod(() => SessionFactory.Get());
_container.Register(Component.For<IDataAccess>().ImplementedBy<SqlDataAccess>());
_container.Register(Component.For<IWorker>().ImplementedBy<DocumentWorker>());
_container.Register(Component.For<IDependency>().ImplementedBy<SomeDependency>());
}
protected override void OnStart(string[] args)
{
_engine = _container.Resolve<Engine>();
_engine.Start();
}
protected override void OnStop()
{
_container.Release(_engine); //1?
}
}
The "Engine":
class Engine
{
IWindsorContainer _container
public Engine(IWindsorContainer container)
{
_container = container;
}
public void Start()
{
Task.Factory.StartNew(() => Work());
}
public void Work()
{
var worker = _container.Resolve<IWorker>();
worker.DoWork();
_container.Release(worker); //2?
}
}
A Worker Task:
class Worker : IWorker
{
IDataAccess _accessor;
IWindsorContainer _container;
public Worker(IDataAccess accessor, IWindsorContainer container)
{
_accessor = accessor;
_container = container;
}
public void DoWork()
{
var depen = _container.Resolve<IDependency>();
//DoWork
_container.Release(depen); //3?
}
}
Thanks, I'll be happy to elaborate further if more detail is needed.
I know in most cases Castle Windsor Recommends 1 Conatiner per app Domain, however you can have as many as you want. There are IOC design Patterns where multiple containers are used, such as 1 container per dll. In this senario you may want one container per thread or process and one for the rest of the application. Hope this helps
My experience is that setting up a container is rather costly, which is fine as it's usually a one time experience.
But if we do it per Task, like mentionned here, we lose the performance gain, we probably wanted by using Tasks.
I'm strugling a bit with this as well. I'm using HybridPerWebRequest/Thread lifestyles as most of the components are shared and I don't want instantiators needing to know the inner details of the lower levels, so they should use the Castle Installers I'm giving them.
The problem I now have is also related to the fact that Per Task creation isn't really supported, so I lose some of my "StateFull" Services when the newly spawned task is not using the same thread as the main thread.
Castle will work fine, as it will generate a new object. But in this case I lose the State of the main thread.
I'm thinking of making it less formante by dropping the Task Creation.

Categories