使用 `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`
- 当我对
Task
使用 return
时会抛出上述问题(在较高的处理量下,但在较低的处理量下没问题)
- 然而,当我
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
我有一段代码抛出:
is registered using the 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope`
- 当我对
Task
使用return
时会抛出上述问题(在较高的处理量下,但在较低的处理量下没问题) - 然而,当我
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