假设我们有这个类 - MyClass
MyClass具有将不同类型的列表转换为 XDocument 的方法
作为一个例子,我们只看一种方法,Convert
我可以把这个方法写成:
public XDocument Convert<T>(IList<T> myList)
{
XDocument doc = new XDocument("root");
//Do some synchronous work
return doc;
}
Run Code Online (Sandbox Code Playgroud)
或者我可以像下面这样写:
public Task<XDocument> Convert<T>(IList<T> myList)
{
XDocument doc = new XDocument("root");
//Do some synchronous work
return Task.FromResult(doc);
}
Run Code Online (Sandbox Code Playgroud)
现在想象一下,我们想将其卸载到我们程序的另一部分中的任务,而其他一些任务正在做一些工作,然后等待它们全部完成,然后再在异步方法中做一些其他工作。
我知道使用该方法的第一个版本,我可以这样做:
some async method...
Task t = Task.Run(() => myClass.Convert<T>(IList<T>);
Task t2...
Task t3...
await Task.WhenAll(t, t2, t3);
Run Code Online (Sandbox Code Playgroud)
但是使用该方法的第二种形式,能够做到这一点似乎更简单:
some async method...
Task t = myClass.Convert<T>(IList<T>);
Task t2...
Task t3...
await Task.WhenAll(t, t2, t3);
Run Code Online (Sandbox Code Playgroud)
我的问题是:
像第二个例子那样设计方法有什么缺点吗?返回一个 Task 以便于在代码库的其他地方作为 Task 运行,即使它是同步的。或者这更多的是关于意图?
我知道这可能被认为是一个自以为是的问题,所以在我给它足够的时间来获得一些回应之后,我可能会将它从 SO 中删除。否则,如果考虑一个足够具体和好的问题,我会离开它。
像第二个例子那样设计方法有什么缺点吗?
是的。该方法是同步的,但具有异步签名。这是一个糟糕的设计选择。
这很容易导致意外误用。比如说……
能够做到似乎更简单
该代码不会像您认为的那样工作。这些任务不会并行运行。因为代码是同步的;它只有一个异步签名。
如果您认为 usingTask.Run作为伪异步方法的实现,那也被认为是一种不好的做法。