创建一个使用返回 Task<T> 的方法但与返回 T 的方法同步的类的任何缺点

Rya*_*son 1 c# oop

假设我们有这个类 - 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 中删除。否则,如果考虑一个足够具体和好的问题,我会离开它。

Ste*_*ary 5

像第二个例子那样设计方法有什么缺点吗?

是的。该方法是同步的,但具有异步签名。这是一个糟糕的设计选择。

这很容易导致意外误用。比如说……

能够做到似乎更简单

该代码不会像您认为的那样工作。这些任务不会并行运行。因为代码是同步的;它只有一个异步签名

如果您认为 usingTask.Run作为伪异步方法的实现,那也被认为是一种不好的做法

  • @RyanWilson:我建议[在*调用*方法时使用`Task.Run`,而不是作为该方法的实现](https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-使用.html)。 (2认同)