我有一个代码块,它抛出:
使用"异步作用域"生活方式注册,但在活动(异步作用域(作用域的上下文之外请求实例`
- 当我将
return
用于Task
时(在较高的卷上,但在较低的处理卷上可以(,会引发以上情况 - 然而,当我
await
、Task
、Simple Injector不抛出时,无论直通请求量如何,它都可以正常工作
与Simple Injector相比,我理解这可能更像是一个以异步为中心的问题,但有什么见解可以解释为什么用await
替换return
可以解决这个问题?
提前感谢,我很担心;工作";使用CCD_ 7是否潜在地隐藏了一个更大的问题。
背景:
我有下面的循环,由一个工人定义项目(要调度的任务(:
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;
});
}
访问t.Result
时,上述ContinueWith
发生异常:
CommandHandler是使用"异步作用域"生活方式注册的,但该实例是在活动(异步作用域(作用域的上下文之外请求的。请参阅https://simpleinjector.org/scoped有关如何应用生活方式和管理范围的更多信息。
通过而不是等待Task
,您正在与主操作并行执行Task
。并行意味着代码变成多线程。
这意味着原始CCD_ 15可能会在CCD_。这会导致您遇到异常。但在其他情况下,Scope
可能会在执行Task
期间被处理掉。这将导致在Task
运行时处理对象。这可能会导致奇怪的多线程问题。
这意味着,在您的情况下,您应该绝对等待从dispatchFunc
返回的Task
。