当前位置: 首页 > 知识库问答 >
问题:

如何实现返回TaskT>的接口方法?

汪兴旺
2023-03-14

我有一个接口

interface IFoo
{
  Task<Bar> CreateBarAsync();
}

创建 有两种方法,一种是异步的,一种是同步的。我想为这两个方法中的每一个提供一个接口实现。

对于异步方法,其实现可能如下所示:

class Foo1 : IFoo
{
  async Task<Bar> CreateBarAsync()
  {
    return await AsynchronousBarCreatorAsync();
  }
}

但是我应该如何实现使用同步方法创建 的类 呢?

我可以实现方法以同步运行:

  async Task<Bar> CreateBarAsync()
  {
    return SynchronousBarCreator();
  }

然后,编译器将警告不要在方法签名中使用 :

此异步方法缺少'await'运算符,将同步运行。考虑使用'await'运算符等待非阻塞API调用,或'await task.run(...)'在后台线程上执行与CPU绑定的工作。

或者,我可以实现显式返回 的方法。在我看来,这样代码的可读性就会降低:

  Task<Bar> CreateBarAsync()
  {
    return Task.Run(() => SynchronousBarCreator());
  }

从性能的角度来看,我认为这两种方法的开销差不多,或者?

我应该选择哪种方法;同步实现 方法,还是显式地将同步方法调用包装在 中?

编辑

我正在从事的项目实际上是一个。NET4项目,带有来自Microsoft async NuGet包的async/await扩展。在.NET4上,可以将 替换为 。我有意识地在上面的示例中使用了.NET4.5方法,希望能使首要问题更加清晰。

共有3个答案

慕容恩
2023-03-14

如果您使用的是.NET4.0,则可以使用 :

Task<Bar> CreateBarAsync()
{
    var tcs = new TaskCompletionSource<Bar>();
    tcs.SetResult(SynchronousBarCreator());
    return tcs.Task
}

最后,如果您的方法没有任何异步性,您应该考虑公开一个同步端点(codeCreatebar/code>),它将创建一个新的 。这样就不会有什么意外,也不需要用冗余的 包装。

舒宏富
2023-03-14

请尝试以下操作:

class Foo2 : IFoo
{
    public Task<Bar> CreateBarAsync()
    {
        return Task.FromResult<Bar>(SynchronousBarCreator());
    }
}

使用提供的值创建指定类型的已经完成的任务。

安经纶
2023-03-14

当您必须从接口实现异步方法并且您的实现是同步的时,您可以使用Ned's解决方案:

public Task<Bar> CreateBarAsync()
{
    return Task.FromResult<Bar>(SynchronousBarCreator());
}

使用此解决方案,方法看起来是异步的,但实际上是同步的。

或您提出的解决方案:

  Task<Bar> CreateBarAsync()
  {
    return Task.Run(() => SynchronousBarCreator());
  }

这样方法才是真正的异步方法。

您没有一个通用的解决方案来匹配“如何实现返回任务的接口方法”的所有情况。这取决于上下文:您的实现是否足够快,以至于在另一个线程上调用它是毫无用处的?如何使用这个接口?何时调用这个方法(它会冻结应用程序吗?甚至有可能在另一个线程中调用您的实现吗?

 类似资料:
  • 有一个界面WebElement。 我想做一个包装器UIElement,它实现了WebElement。 我已经重写了所有方法。 但是返回List的findElementS方法面临一个问题 这是我的方法,IDE没有给出上面的错误: 这是UIElement类和构造函数:

  • 主要内容:1.接口相互作用,2.返回格式,3.数据,4.控制层控制器,5.美观美化,6.优雅优化,7.其他优化方案1.接口相互作用 前端和前端进行交互,前端按约定的请求URL路径,并合并相关参数,进入服务器接收请求,进行业务处理,返回数据给前端。 2.返回格式 我们可以参考这样的设计,这样的好处就把错误类型归类到某个区间内,如果区间不够,可以设计成4个数字。 这样前端开发人员在得到返回值后,根据状态码就可以知道,大概什么错误,再根据消息相关的信息描述,可以快速定位。 状态码和信息就会一一对应,比

  • 我有一个接口,它的函数当前返回它自己。但是,我希望任何实现类都返回该类,而不是基接口。例如,在这个简化的示例中,它工作得很好: 这显然是失败的,因为重写函数不再与接口中的声明匹配。 我需要baz()返回Class而不是Interface,因为调用者可以以任意顺序调用bar和baz任意次数,但是目前所有bar()调用必须在所有baz()调用之前,除非我们重复地向下调用。 更复杂的是foo()函数,它

  • 问题内容: 我有一个定义方法的接口。我有一个 实现 此接口的结构。在其中,我已经从该接口实现了方法,并且还定义了其他方法。 例如: 在操场上:https : //play.golang.org/p/B1GgoNToNl_l 在此,WagTail()不是Animal接口的一部分,但属于Dog结构。运行此代码会出现错误 dog.WagTail未定义(动物类型没有字段或方法WagTail)。 有没有一种

  • 问题内容: 假设我正在设计类似以下界面的内容: 但是,需要注意的是,for的返回类型和参数匹配具体的实现,而不仅仅是。也就是说,如果我具有该实现,则需要具备以下条件: 如上所述,不会引起任何编译错误,但是不能保证在所有实现中返回类型都匹配。当然,甚至不会编译,因为签名与接口不匹配。 一种候选解决方案是在泛型中使用自引用或递归范围: 这将使我得到我想要的东西,但有一个例外:其他实现可能传递错误的泛型

  • 问题内容: 如何在实现类中强制执行方法getFoo(),返回相同实现类类型的列表。 现在,实现Bar的类将返回实现Bar的任何类的对象。我想使其更加严格,以便实现Bar的类在getFoo()中仅返回其类型的对象列表。 问题答案: 不幸的是,这不能由Java的类型系统强制执行。 但是,您可以通过使用以下方法来达到非常接近的效果: 然后您的实现类可以像这样实现它: 但是没有什么可以阻止另一个类这样做: