使用`ContinueWith`时,简单注入器“在活动异步作用域作用域的上下文之外请求实例”

问题描述

我有一个抛出的代码块:

使用“异步作用域”生活方式进行注册,但是在活动(异步作用域)作用域的上下文之外请求实例。

  1. 当我将return用于Task时,会抛出上述错误(大容量时,但处理量较小时,可以)
  2. 但是,当我await Task时,无论吞吐量请求量如何,它都不会起作用。

相对于Simple Injector,我理解这可能是一个更关注异步的问题,但是有何见解为何将return替换为await 解决这个问题?

在此先感谢您使用await进行“工作”是否会隐藏更大的问题。

背景

我有以下循环,由工作队出队物品(要分派的任务):

void Loop()
{
    while (cancellationToken.IsCancellationRequested == false)
    {
        item = await this.queue.Reader.ReadAsync(cancellationToken);
        
        await dispatchItemAsync(item,(item,dispatcher) =>
        {
            return dispatcher
                .SendAsync(((ISendItem)item).GetHandler,item.Message,item.CancellationToken)
                .ContinueWith(t => item.taskcompletionsourceWrapper.SetResult(t.Result),TaskContinuationoptions.runcontinuationsAsynchronously);
        });
    }
}

上述循环中的dispatchItemAsync在下面:

protected override async Task dispatchItemAsync(
    IQueueItem item,Func<IQueueItem,IThreadStrategy,Task> dispatchFunc)
{
    // cast the passed item from channel queue
    var queueItemWithStack = item as IQueueItemWithStack;

    using (AsyncScopedLifestyle.BeginScope(this.container))
    {
        var dispatcher = container.GetInstance<InParallel>();
        // the above is an interface of delegates that is used to call functions
        
        // return throws SimpleInjector outside of scope exception (intermittent,// always for high request volume)
        return dispatchFunc(queueItemWithStack,dispatcher);

        // using await no exception is thrown
        // await dispatchFunc(queueItemWithStack,dispatcher);
    }
}

InParallel包含dispatchFunc调用函数的情况下,以下内容(最终通过链)称为:

public Task<object> SendAsync(
    Func<SendFunction> getHandler,object request,CancellationToken cancellationToken = default)
{
    return this
        .inCaller
        .SendAsync(getHandler,request,cancellationToken)
        .ContinueWith(t =>
        { 
            // snip some code
            // the below throws if dispatchItemAsync call us with return
            // but is OK if dispatchItemAsync called us with await instead
            return t.Result;
        });
}

访问ContinueWith时,上述t.Result会发生异常:

CommandHandler是使用“异步作用域”生活方式注册的,但是在活动(异步作用域)作用域的上下文之外请求实例。有关如何应用生活方式和管理范围的更多信息,请参见https://simpleinjector.org/scoped

解决方法

通过等待Task,您正在与主操作并行执行Task 。并行意味着代码成为多线程。

这意味着原始Scope可能会在Task完成执行之前被处理掉。这会导致您遇到异常。但是在其他情况下,Scope可能会在执行Task时被处理掉。 Task正在运行时,这将导致对象被丢弃。这可能会导致奇怪的多线程问题。

这意味着,根据您的情况,您应该绝对等待Task返回的dispatchFunc

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...