使用 `ContinueWith` 时的简单注入器 "instance is requested outside the context of an active (Async Scoped) scope"

Simple Injector "instance is requested outside the context of an active (Async Scoped) scope" when using `ContinueWith`

我有一段代码抛出:

is registered using the 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope`

  1. 当我对 Task 使用 return 时会抛出上述问题(在较高的处理量下,但在较低的处理量下没问题)
  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 is registered using the 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope. Please see https://simpleinjector.org/scoped for more information about how apply lifestyles and manage scopes.

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

这意味着原始 Scope 可能会在 Task 完成执行之前被处理掉。这会导致您遇到异常。但在其他情况下,Scope 可能会在 Task 执行期间被处理掉。这将导致对象在 Task 为 运行 时被处理掉。这可能会导致奇怪的 multi-threading 问题。

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

返回的 Task