使用语句与异步任务内部不等待
本文关键字:内部 等待 任务 异步 语句 | 更新日期: 2023-09-27 18:37:05
-
我创建了一个 IDisposable 对象,用于记录 Dispose 上的执行时间。
-
然后,我创建了一个 RealProxy,它使用此对象来记录我的业务类的任何方法调用的时间
。 我的业务类使用异步方法,然后在任务完成之前保留 using 语句,然后记录错误的执行时间。
这是我的代码:
/// <summary>
/// Logging proxy with stopwatch
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class LoggingProxy<T> : RealProxy// where T : MarshalByRefObject
{
private ILog _logger;
private readonly T _instance;
private LoggingProxy(T instance, ILog logger)
: base(typeof(T))
{
_logger = logger;
_instance = instance;
}
/// <summary>
/// Create the Transparent proy for T
/// </summary>
/// <param name="type">An implementation type of T</param>
/// <returns>T instance</returns>
public static T Create(ILog logger)
{
logger.DebugFormat("[{0}] Instantiate {1}", "LoggingProxy", typeof(T).Name);
var instance = (T)Activator.CreateInstance(typeof(T), logger);
//return the proxy with execution timing if debug enable in logger
if (logger.IsDebugEnabled)
return (T)new LoggingProxy<T>(instance, logger).GetTransparentProxy();
else
return instance;
}
/// <summary>
/// Invoke the logging method using Stopwatch to log execution time
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public override IMessage Invoke(IMessage msg)
{
var methodCall = (IMethodCallMessage)msg;
var method = (MethodInfo)methodCall.MethodBase;
string methodName = method.Name;
string className = method.DeclaringType.Name;
//return directly methods inherited from Object
if (method.DeclaringType.Name.Equals("Object"))
{
var result = method.Invoke(_instance, methodCall.Args);
return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
}
using (var logContext = _logger.DebugTiming("[{0}] Execution time for {1}", className, methodName))
{
_logger.DebugFormat("[{0}] Call method {1}", className, methodName);
//execute the method
//var result = method.Invoke(_instance, methodCall.Args);
object[] arg = methodCall.Args.Clone() as object[];
var result = method.Invoke(_instance, arg);
//wait the task ends before log the timing
if (result is Task)
(result as Task).Wait();
return new ReturnMessage(result, arg, 0, methodCall.LogicalCallContext, methodCall);
}
}
_logger。调试计时方法启动秒表并将其记录在"处置"上。 我发现使其与异步方法一起使用的唯一方法是使用该行:
//wait the task ends before log the timing
if (result is Task)
(result as Task).Wait();
但我只是觉得这样做打破了异步方法的所有好处。
-> 如果您有关于如何正确实现的建议
-> 知道调用wait()对代理的真正影响吗?
您可以使用
Task.ContinueWith():
public override IMessage Invoke(IMessage msg)
{
var methodCall = (IMethodCallMessage)msg;
var method = (MethodInfo)methodCall.MethodBase;
string methodName = method.Name;
string className = method.DeclaringType.Name;
//return directly methods inherited from Object
if (method.DeclaringType.Name.Equals("Object"))
{
var result = method.Invoke(_instance, methodCall.Args);
return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
}
var logContext = _logger.DebugTiming("[{0}] Execution time for {1}", className, methodName);
bool disposeLogContext = true;
try
{
_logger.DebugFormat("[{0}] Call method {1}", className, methodName);
//execute the method
//var result = method.Invoke(_instance, methodCall.Args);
object[] arg = methodCall.Args.Clone() as object[];
var result = method.Invoke(_instance, arg);
//wait the task ends before log the timing
if (result is Task) {
disposeLogContext = false;
((Task)result).ContinueWith(() => logContext.Dispose());
}
return new ReturnMessage(result, arg, 0, methodCall.LogicalCallContext, methodCall);
}
finally
{
if (disposeLogContext)
logContext.Dispose();
}
}
不要在任务上调用 Wait() - 这会改变行为并可能导致死锁。