首页 > 解决方案 > 使用`ContinueWith`时,简单注入器“在活动(异步范围)范围的上下文之外请求实例”

问题描述

我有一段代码抛出:

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

  1. 当我return用于Task(在较高的容量,但在较低的处理量)时,会抛出上述情况
  2. 但是,当我没有抛出 Simple Injector时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);
    }
}

包含由InParalleldispatchFunc行调用的函数,以下是(最终通过链)调用:

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 使用“Async Scoped”生活方式注册,但在活动(Async Scoped)范围的上下文之外请求实例。有关如何应用生活方式和管理范围的更多信息,请参阅https://simpleinjector.org/scoped

标签: c#multithreadingasync-awaitsimple-injector

解决方案


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

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

这意味着,在您的情况下,您绝对应该等待TaskdispatchFunc.


推荐阅读