异步任务和简单注入器生命周期范围

时间:2015-07-10 15:00:45

标签: c# multithreading asynchronous inversion-of-control simple-injector

我有以下方法可以解析返回任务的IConsumeAsync

private Task ConsumeMessageAsync<TMessage, TConsumer>(TMessage message)
    where TMessage : class
    where TConsumer : IConsumeAsync<TMessage>
{
    var tsc = new TaskCompletionSource<object>();
    var instance = (IConsumeAsync<TMessage>)container
        .GetInstance(typeof(TConsumer));

    instance
        .Consume(message)
        .ContinueWith(task =>
        {
            if (task.IsFaulted && task.Exception != null)
            {
                tsc.SetException(task.Exception);
            }
            else
            {
                tsc.SetResult(null);
            }
        });

    return tsc.Task;
}

我需要使用生命周期范围ala

来包装它
using(var scope = container.BeginLifetimeScope()){
}

我尝试了以下但是它没有100%的工作

var scope = container.BeginLifetimeScope();

var wrapper = ConsumeMessageAsync<TMessage, TConsumer>(message);
wrapper.ContinueWith(x => scope.Dispose());
wrapper.Start();

我收到以下错误:

  

其他信息:使用LifetimeScope实例是不安全的   跨线程。确保一生的完整操作   范围环绕在同一个线程中执行并确保   LifetimeScope实例与它放在同一个线程上   得到了。使用ManagedThreadId 27在线程上调用Dispose,   但是在ID为21的线程上创建。

我不太确定如何使用using语句在.NET中包装异步任务,尝试使用额外的包装器任务来控制流程。

1 个答案:

答案 0 :(得分:6)

您需要使用AsyncScopedLifestyle代替。 ThreadScopedLifestyle(以前称为LifetimeScopeLifestyle)创建了一个特定于线程的作用域,而AsyncScopedLifestyle创建了一个与异步方法的逻辑控制流一起流动的作用域。

// using SimpleInjector.Lifestyles;

using (AsyncScopedLifestyle.BeginScope(container)) {
    var service = container.GetInstance<ISomeService>();
    // ...
}