2

I'm using autofac in an owin-driven web api project. I've come to a place where I need to "Fire and Forget" some processing of data. This normally isn't an issue. But since the dependencies are controlled by the per-request lifetime scope managed by the autofac middleware. I cannot use un-managed resources (which is what i need to do) in my non-awaited async method.

//for example...
public async Task<IEnumerable<MyThings>> GetThings(){
     var things = await _thingRepo.GetInterestingThingsAsync();
     //fire and forget. -- not awaiting
     InjectedObject.DoThingsAsync(things);
     return things;
}

The problem here is that I need to use other injected resources (un-managed resources) inside DoThingsAsync. Currently this breaks because they're disposed of when the Owin Request ends.

I could create a child lifetime scope for each invocation but I'm hoping their might be a cleaner way to do such things..

calebboyd
  • 5,744
  • 2
  • 22
  • 32
  • possible duplicate of [Can multiple Autofac lifetime scopes be specified on a registration?](http://stackoverflow.com/questions/16817655/can-multiple-autofac-lifetime-scopes-be-specified-on-a-registration) – joelmdev May 12 '14 at 21:51
  • @joelmdev I don't really have an issue with dependency registration.. Though it did link to this [scenario](http://stackoverflow.com/q/8658946/2592994) which presented (in the question) the same solution I came to, but the op had a different issue. – calebboyd May 13 '14 at 18:30

1 Answers1

2

Update:

With the dawn of .Net Framework 4.5.2 I can now use

HostingEnvironment.QueueBackgroundWorkItem Which is preferred Because it will keep IIS from recycling before the work item completes.


I think I found a solution for my use case..

I just Inject this class where I need it:

public class AsyncTask : IAsyncTask
{
    private ILifetimeScope _lifetimeScope;
    public AsyncTask(ILifetimeScope lifeTimeScope)
    {
        //disposed of by owning scope...
        _lifetimeScope = lifeTimeScope;
    }
    public async Task Fire<T>(Func<T,Task> asyncAction)
    {
        using (var scope = _lifetimeScope.BeginLifetimeScope())
        {
            await asyncAction(scope.Resolve<T>());
        }
    }
}
public interface IAsyncTask
{
    Task Fire<T>(Func<T, Task> action);
}

Then..

_asyncTask.Fire<IEmailService>(svc => svc.SendMillionsOfEmailsAsync(content));
calebboyd
  • 5,744
  • 2
  • 22
  • 32