在同步对象中实现异步接口

     2023-03-07     223

关键词:

【中文标题】在同步对象中实现异步接口【英文标题】:Implementing Asynchronous Interfaces in Synchronous objects 【发布时间】:2018-11-04 10:10:05 【问题描述】:

在学习异步编程时,我一直在尝试实现一个既适用于异步类又适用于同步类的接口,但我看到了相互冲突的做法。

举个例子,如果我尝试使用 On() 和 Off() 方法实现 ILight 接口。

public interface ILight

    void On();
    void Off();

使用WiredLight,这些方法是同步的,并且都是快速的 CPU 密集型工作。

public class WiredLight : ILight

    private bool _powered;

    public void On()
    
        _powered = true;
    

    public void Off()
    
        _powered = false;
    

但是对于WirelessLight,这些方法是异步的,其中有 IO 绑定工作。 (这里的方法不遵循接口签名,而是以异步方式实现,以避免异步无效。)

public class WirelessLight : ILight

    public async Task On()
    
        await EnablePowerAsync();
    

    public async Task Off()
    
        await DisablePowerAsync();
    

阅读(here 和here),这样做的方法只是在接口中强制异步签名,然后所有同步调用将被重构为异步(参考:Async all the way)。这对我来说听起来不错,但我还没有真正看到有关如何处理同步方法(来自WiredLight)的任何信息。与this 问题不同,没有IO 绑定操作,因此没有什么可以等待的。我考虑将它们包装在异步调用中(return Task.Run(() => _powered = true; );),但这与大多数recommendations 相反。我也考虑过简单地返回一个已经完成的任务(类似于this 或this)

public class WiredLight : ILight

    public Task OnAsync()
    
        _powered = true;
        return Task.CompletedTask;
    

但是在同步运行时将方法呈现为异步是谎言,并且也反对推荐。此外,看起来返回 Task.CompletedTask 可能会将相同的任务返回给不同的调用。目前我不知道这会在哪里引起问题,但似乎会引起问题。

对于不返回任何内容并且确实应该同步的方法实现异步接口,是否存在公认的做法?

【问题讨论】:

是什么让你想把这个接口写成异步的? “我也考虑过简单地返回一个已经完成的任务”——是的,这是正确的做法。我一直使用Task.FromResult() 而不是CompletedTask,如果您担心任务对象身份,那么FromResult() 可能会解决这个问题。 @zaitsman 使用上面的示例,我已经有一个实现ILightWiredLight,我刚刚添加了WirelessLight,它还需要实现ILight。 (基本上我在 Async Zombie 病毒中) 【参考方案1】:

从同步方法执行异步操作可能真的很危险。没有完美的方法可以做到这一点,而且您可能经常遇到线程饥饿问题的死锁。这不是你想要发现自己的情况。

另一方面,从异步方法同步操作是安全的。当然,你在对调用者撒谎,但这并不是真正的问题,除非他想并行执行你的代码(在这种情况下,他会在注意到问题后简单地添加一个Task.Run,你也应该在cmets)。在等待完成的任务时,运行时足够智能以优化调用,因此对调用者的性能影响非常小,对于大多数应用程序来说可以忽略不计。

因此,如果您有理由认为您需要在您的接口实现之一中执行异步代码,请不要犹豫,将其标记为异步。对于实际上是同步的实现,返回一个已完成的任务通常是最好的做法:

public Task DoSomethingAsync()

    DoSomething(); 
    return Task.CompletedTask;

我建议不要在方法内部使用Task.Run,因为它通常是不可取的,并且可以在需要时由调用者轻松添加。 .net 中的async 表示该方法可以异步完成,而不是它会很快返回。

【讨论】:

为啥在具有多个接口() 的对象中实现 QueryInterface() 时我需要显式向上转换

】为啥在具有多个接口()的对象中实现QueryInterface()时我需要显式向上转换【英文标题】:WhyexactlydoIneedanexplicitupcastwhenimplementingQueryInterface()inanobjectwithmultipleinterfaces()为什么在具有多个接口()的对象中实现QueryInterface()时我需要显式... 查看详情

在 PHPUnit 中实现给定接口的模拟对象上的未定义方法?

】在PHPUnit中实现给定接口的模拟对象上的未定义方法?【英文标题】:UndefinedmethodonmockobjectimplementingagiveninterfaceinPHPUnit?【发布时间】:2012-09-1723:23:09【问题描述】:我是单元测试和PHPUnit的新手。我需要一个模拟,我可以完全控... 查看详情

是否可以在 GraphQL 中实现多个接口?

...问题讨论】:【参考方案1】:是的。如spec中所述:一个对象类型可以声明它实现了一个或多个独特的接口。请记住,生成的对象必须是“它实现的 查看详情

如何在一个类中实现异步

...步编程方式。方法四:Promise模式ES6中提供了原生的Promise对象,这个模式最开始只是一个构想,后来由一些框架库实现。Promise对象代表了未来才会知道结果的事件。Promise的基本思路就是,将需要异步执行的事件储存起来,然后... 查看详情

使用消息传递接口在 Python 中实现多处理 [关闭]

】使用消息传递接口在Python中实现多处理[关闭]【英文标题】:ImplementmultiprocessinginPythonwithamessagepassinginterface[closed]【发布时间】:2021-03-1204:49:55【问题描述】:我正在尝试将一些JavaScript代码转换为Python,但是JavaScript以异步方式... 查看详情

如何在 Java 中实现包装装饰器?

...布时间】:2016-04-0807:20:35【问题描述】:问题是创建现有对象的动态增强版本。我无法修改对象的Class。相反,我必须:子类化它将现有对象包装在新的Class中将所有原始方法调用委托给包装对象实现由另一个接口定义的所有方... 查看详情

在 Java 中实现和使用通用的抽象接口

...型的,需要有一个构造函数来接受CharSequence的子类的任何对象。这是我目前拥有的:谓词.javapackagepred 查看详情

node.js中实现同步操作的3种实现方法

这篇文章主要介绍了node.js中实现同步操作的3种实现方法,本文用实例讲解一些需要同步操作的情况下,如何编程实现,需要的朋友可以参考下众所周知,异步是得天独厚的特点和优势,但同时在程序中同步的需求(比如控制程序的... 查看详情

node.js中实现同步操作的3种实现方法

...所周知,异步是得天独厚的特点和优势,但同时在程序中同步的需求(比如控制程序的执行顺序为:func1->func2->func3)也是很常见的。本文就是对这个问题记录自己的一些想法。需要执行的函数: varfunc1=function(req,res,callba... 查看详情

如何在 ASP.NET 页面中实现异步加载?

】如何在ASP.NET页面中实现异步加载?【英文标题】:HowtoimplementasynchronousloadinginASP.NETpage?【发布时间】:2012-02-0623:11:53【问题描述】:ASP.NET页面如何实现异步加载?我的ASP.NET页面中有3个部分。所有部分都是独立的。LoadSection1();... 查看详情

java示例代码_在Java中实现同步方法超时

java示例代码_在Java中实现同步方法超时 查看详情

如何在 JS/TS 中实现伪阻塞异步队列?

】如何在JS/TS中实现伪阻塞异步队列?【英文标题】:HowtoimplementapseudoblockingasyncqueueinJS/TS?【发布时间】:2018-04-1919:48:11【问题描述】:所以这里有一个矛盾:我想在javascript/typescript中创建一个异步阻塞队列(如果你可以在没有ty... 查看详情

如何在 Java 中实现同步方法超时?

】如何在Java中实现同步方法超时?【英文标题】:HowtoimplementsynchronousmethodtimeoutsinJava?【发布时间】:2013-06-1810:55:02【问题描述】:我有一个同步执行路径,它需要在给定的时间范围内完成或超时。假设我有一个带有main()方法的... 查看详情

在unity中实现简单的伪时间同步

在Unity中实现简单的伪时间同步,只是读取数据库所在电脑的当前时间代码如下:usingUnityEngine;usingSystem.Collections;usingSystem.Runtime.InteropServices;usingSystem.Data;usingSystem.Data.SqlClient;publicclassChangeTime{//Kernel32.dll在32位 查看详情

typeerror:'stepup'调用了一个没有在jquery中实现接口htmlinputelement的对象(代码片段)

我使用jquery$.post方法调用php文件。在重新获取数据时,我收到错误。我在google上搜索过,找到了4到5个解决方案,但那些都没有用。请帮我。这是我的代码,jQuery的$(document).ready(function()$("[name='side_door_on_size']").click(function()varside_d... 查看详情

在 VBA 中实现接口的事件

】在VBA中实现接口的事件【英文标题】:Implementinginterface\'seventinVBA【发布时间】:2019-02-2713:19:00【问题描述】:我有一个界面IView:OptionExplicitPublicEventOnClientSelected()PublicPropertyGetClientNames()AsVariantEndProperty(...)但我无法在我的用户... 查看详情

在 C++ 中实现多个接口

】在C++中实现多个接口【英文标题】:Implementingmultipleinterfacesinc++【发布时间】:2013-05-2010:07:44【问题描述】:我的接口层次结构如下:classApublic:voidfoo()=0;;classB:publicApublic:voidtestB()=0;;classC:publicApublic:voidtestC()=0;;现在,我想通过... 查看详情

在 Python 中实现 Typescript 接口

】在Python中实现Typescript接口【英文标题】:ImplementingTypescriptinterfacesinPython【发布时间】:2020-08-3009:08:36【问题描述】:我正在寻找一些关于在Python中实现一组仅数据值“接口”的最佳方法的建议,这些接口相当于它们的打字稿... 查看详情