I have an ASP.Net MVC3 solution running a batch import process which fetches data from a web-service. For each row/loop, the process needs to send up to four emails. I'd like to fire these emails off in background threads so that the main thread doesn't have to wait for the emails to be sent. The child email thread needs to update the database audit table on email send completion or failure.
The issue I'm having is that I use Unity to inject the IEmailer class into my main process thread, which also assigns the 'main process thread' datacontext into the emailer class. So I get errors when the datacontext has already been closed when the emailer tries to update the audit table if the main loop has already finished (a plausible scenario).
How do I tell Unity to assign a new datacontext to my new emailer threads, or how do I tell my emailer class to use a different unity container (configured with Transient datacontext, I guess?)?
Here's my stripped down code. (I realise I could just instantiate a 'new MyDataContext()' inside the emailer but there is definitely a better way).
Any help, suggestions, ideas or comments will be greatly appreciated - thank you!
IOC Container
this.unityContainer = new UnityContainer()
.RegisterType<IDataProvider, DataProvider>()
.RegisterType(typeof(IEmailer), typeof(Emailer))
.RegisterType<DbContext, MyDataContext>(new HierarchicalLifetimeManager());
Import class (main thread)
public class DataSyncer : IDataSyncer
{
public DataSyncer(IDataProvider dataProvider, IEmailer emailer) {
this.dataProvider = dataProvider;
this.emailer = emailer;
}
public void Import(Guid key) {
// some import code
emailer.EmailAddress = "someone@somewhere.com";
emailer.Subject = "subject line";
new Thread(emailer.SendMail).Start(); // send email in new thread
}
}
Emailer class (for child threads)
public class Emailer : IEmailer
{
[Dependency]
public IDataProvider DataProvider { get; set; }
// etc
}
DataProvider (contains datacontext via ctor injection)
public DataProvider(MyDataContext context, // etc) { // etc }