【发布时间】:2017-10-17 00:33:29
【问题描述】:
在下面的示例代码中(由于 if 检查无效,它无法编译),我需要确定 returnValue 是“TResult 的任务”还是任务或其他类型。如果是 TResult 的 Task 我可以访问并记录 Result 属性,如果是 Task,没有返回值,我会记录“[Task]”,如果不是这两个,那么我可以直接记录返回值或记录一个[“空”]
public void LogReturnValue(obj returnValue)
{
var valueToLog = "";
if(returnValue is Task)
{
valueToLog = "[Task]";
} else if(returnValue is Task<T>)
{
valueToLog = returnValue.Result;
}
else
{
valueToLog = returnValue ?? "[null]"
}
this.logger.Log(valueToLog);
}
我想确定returnValue是TResult的Task还是Task,如果是后者,我需要从Result中提取适当的值。一 我的想法是检查 IsGenericType 属性,但我不确定 如果这将永远有效。
【问题讨论】:
-
Task<T>扩展Task。如果对象是Task<T>,那么它将通过第一次检查。泛型检查必须在非泛型类型的测试之前进行。但是这个问题对我来说意味着您正在做一些奇怪的事情并且可能是错误的;你能说说你为什么要做这种奇怪的事情吗? -
此外,获取任务的结果几乎总是非常错误的事情。该任务可能无法完成!这样做可以使程序死锁!如果任务完成时出现异常怎么办?这将使您的程序崩溃。您的代码不起作用,但如果它确实起作用,它会在很多时候挂起或崩溃您的程序。 你为什么要这样做?
-
@EricLippert 如果我的对象是一个任务,则此问题上下文之外的代码可确保在调用此方法之前它是一个已完成的任务,所以这不是问题。如果它以异常完成,我可以在这里检查并记录一些关于它的信息。我想要完成的是记录 returnValue,如果没有,那很好。该代码只是一个“示例代码”,我明确表示它不会编译,它只是为了帮助传达我想要完成的任务。
-
我知道将 async/await 与同步等待和由此产生的死锁混合是很危险的,但这个问题只是为了看看我如何在运行时提取任务的结果,而对象可能是几乎任何东西。我不明白为什么人们不赞成它。我认为只要您知道自己在做什么,访问 Result 是合理的。同样,我知道这不是最佳做法,应尽可能避免。
-
+1 票。对我来说,我一遍又一遍地使用的典型场景是异步运行器。我以 fire&forget 的方式执行一些异步任务,但是 runner 附加了
ContinueWith,然后我检查结果(即故障、取消等)并以很好的方式向用户显示结果。一切都在掌控之中,但我需要Result。
标签: c# .net async-await task