问题描述
我有一个抛出的代码块:
I have a block of code that throws:
- 当我将
return
用作Task
时,会抛出上述错误(大容量时,但处理量较小时,可以) - 但是当我
await
Task
时,无论通过量请求量如何,它都可以正常工作,简单喷射器不会抛出.
- The above is thrown when I use
return
for theTask
(at higher volumes, but ok at lower processing volumes) - It however works OK regardless of thru-put request volume when I
await
theTask
, Simple Injector does not throw.
我理解,与Simple Injector相比,这可能是一个更加关注异步的问题,但是有何见解为何将return
替换为await
可以解决?
I appreciate this may be more of a async focused question as opposed to Simple Injector, but any insights why replacing return
with await
resolves this?
预先感谢我在工作"期间使用await
是否可能会隐藏更大的问题.
Thanks in advance, I am concerned whilst "working" using await
is it potentially hiding a larger issue.
背景:
我有以下循环,由工作队出队物品(要分派的任务):
I have the following loop that deques items (tasks to be dispatched) by a worker:
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
行所调用的函数,因此以下内容(最终通过链)称为:
With InParallel
containing the function which is called by the dispatchFunc
line, the below is (eventually via a chain) called:
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
会发生异常:
The exception occurs on the above ContinueWith
when the t.Result
is accessed:
推荐答案
通过不等待Task
,您正在并行执行Task
主要操作.并行意味着代码成为多线程.
By not awaiting a Task
, you are executing the Task
in parallel with the primary operation. Parallel means the code becomes multi threaded.
这意味着原始的Scope
可能会在Task
完成执行之前被处理掉.这会导致您遇到异常.但是在其他情况下,Scope
可能会在执行Task
的过程中被处理掉.这将导致在Task
运行时丢弃对象.这可能会导致奇怪的多线程问题.
This means that the original Scope
will likely get disposed before the Task
finished executing. This causes the exception you are experiencing. But in other cases, the Scope
might get disposed off during the execution of the Task
. This will cause objects getting disposed of while the Task
is running. This can cause weird multi-threading issues.
这意味着,根据您的情况,您应该绝对等待从dispatchFunc
返回的Task
.
What this means is that, in your case, you should absolutely await the Task
that is returned from dispatchFunc
.
这篇关于简单注入器“在活动(异步作用域)作用域的上下文之外请求实例".当使用`ContinueWith`时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!