【发布时间】:2017-01-27 14:34:36
【问题描述】:
我们基本上有一个如下所示的类,它使用 Castle.DynamicProxy 进行拦截。
using System;
using System.Collections.Concurrent;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Castle.DynamicProxy;
namespace SaaS.Core.IoC
{
public abstract class AsyncInterceptor : IInterceptor
{
private readonly ILog _logger;
private readonly ConcurrentDictionary<Type, Func<Task, IInvocation, Task>> wrapperCreators =
new ConcurrentDictionary<Type, Func<Task, IInvocation, Task>>();
protected AsyncInterceptor(ILog logger)
{
_logger = logger;
}
void IInterceptor.Intercept(IInvocation invocation)
{
if (!typeof(Task).IsAssignableFrom(invocation.Method.ReturnType))
{
InterceptSync(invocation);
return;
}
try
{
CheckCurrentSyncronizationContext();
var method = invocation.Method;
if ((method != null) && typeof(Task).IsAssignableFrom(method.ReturnType))
{
var taskWrapper = GetWrapperCreator(method.ReturnType);
Task.Factory.StartNew(
async () => { await InterceptAsync(invocation, taskWrapper).ConfigureAwait(true); }
, // this will use current synchronization context
CancellationToken.None,
TaskCreationOptions.AttachedToParent,
TaskScheduler.FromCurrentSynchronizationContext()).Wait();
}
}
catch (Exception ex)
{
//this is not really burring the exception
//excepiton is going back in the invocation.ReturnValue which
//is a Task that failed. with the same excpetion
//as ex.
}
}
....
最初这段代码是:
Task.Run(async () => { await InterceptAsync(invocation, taskWrapper)).Wait()
但是我们在调用这个之后丢失了 HttpContext,所以我们不得不把它切换到:
Task.Factory.StartNew
所以我们可以传入TaskScheduler.FromCurrentSynchronizationContext()
所有这些都很糟糕,因为我们实际上只是将一个线程换成另一个线程。我真的很想更改
的签名void IInterceptor.Intercept(IInvocation invocation)
到
async Task IInterceptor.Intercept(IInvocation invocation)
并摆脱 Task.Run 或 Task.Factory 并制作它:
await InterceptAsync(invocation, taskWrapper);
问题是 Castle.DynamicProxy IIntereceptor 不允许这样做。我真的很想在拦截中等待。我可以做 .Result 但是我打电话的异步调用有什么意义呢?由于无法进行等待,我失去了它能够产生此线程执行的好处。我并没有因为他们的 DynamicProxy 而被 Castle Windsor 困住,所以我正在寻找另一种方法来做到这一点。我们已经研究了 Unity,但我不想替换我们的整个 AutoFac 实现。
任何帮助将不胜感激。
【问题讨论】:
标签: asynchronous castle-dynamicproxy