c# - 使用`ContinueWith`时,简单注入器“在活动(异步范围)范围的上下文之外请求实例”
问题描述
我有一段代码抛出:
使用“异步作用域”生活方式注册,但在活动(异步作用域)作用域的上下文之外请求实例
- 当我
return
用于Task
(在较高的容量,但在较低的处理量)时,会抛出上述情况 - 但是,当我没有抛出 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);
}
}
包含由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 使用“Async Scoped”生活方式注册,但在活动(Async Scoped)范围的上下文之外请求实例。有关如何应用生活方式和管理范围的更多信息,请参阅https://simpleinjector.org/scoped。
解决方案
通过不等待 a Task
,您正在与主要操作Task
并行执行。并行意味着代码变为多线程。
这意味着原始Scope
文件可能会在Task
完成执行之前被处理掉。这会导致您遇到的异常。但在其他情况下,Scope
可能会在Task
. 这将导致对象在Task
运行时被丢弃。这可能会导致奇怪的多线程问题。
这意味着,在您的情况下,您绝对应该等待Task
从dispatchFunc
.
推荐阅读
- multithreading - `mkl_set_num_threads` 会限制 CPU 线程的数量吗?
- mysql - 从有条件的两个表中删除行
- python - 如何将两个值组合成python中字典的一个键?
- php - Laravel 分页链接在 View 中不起作用。获取错误方法 Illuminate\Database\Eloquent\Collection::links 不存在
- postgresql - SERIAL 用于另一列中的每个值
- laravel - 如果在 laravel 中选中了特定的复选框,如何要求一个字段?
- android - 渲染两个 RNCamera 组件时反应原生应用程序给出空白屏幕
- java - 类型参数 t 具有不兼容的上限:视图和片段
- javascript - 包含 2 个字符之间的字符串的正则表达式匹配
- java - Classpath problems while Instrumenting Springboot application