I have a block of code that throws:
is registered using the 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope`
- The above is thrown when I use
returnfor theTask(at higher volumes, but ok at lower processing volumes) - It however works OK regardless of thru-put request volume when I
awaittheTask, Simple Injector does not throw.
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?
Thanks in advance, I am concerned whilst "working" using await is it potentially hiding a larger issue.
Background:
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);
});
}
}
The DispatchItemAsync from the above loop is below:
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);
}
}
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;
});
}
The exception occurs on the above ContinueWith when the t.Result is accessed:
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.