如何在一个类中实现异步
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在一个类中实现异步相关的知识,希望对你有一定的参考价值。
参考技术A 开个线程池,为每个方法的执行分配一个线程,创建一个hashmap结果集,每个方法执行完,将其存入hashmap中,最后通过判断hashmap的大小,判断所有方法线程是否执行完毕,执行完毕则返回该hashmap。异步编程其实很常见,特别是在出线Node.js之后,异步编程更是让很多开发者受益。那么回到最初的地方,传统的前端开发中如何实现异步编程呢?下面列举了js实现异步编程的四种方式。方法一:使用回调函数方法二:事件监听可以定义一个事件,并为这个事件设定处理函数。这样只有当这个时间发生的情况下,对应的处理函数才会被执行。方法三:事件的发布/订阅这个模式在NodeJS以及其他JS框架中都有实现,是一个非常常用的异步编程方式。
方法四:Promise模式ES6中提供了原生的Promise对象,这个模式最开始只是一个构想,后来由一些框架库实现。Promise对象代表了未来才会知道结果的事件。Promise的基本思路就是,将需要异步执行的事件储存起来,然后根据异步事件之行后的结果状态执行下一步的操作。具体的Promise对象的原理和ES6中的使用方法将在下一篇文章中更加深入的进行介绍。
多线程实现。
过程如下
创建一下对象:
robot对象
avi保存对象
行走对象
在robot里使用多线程,2个线程就够,1个执行avi保存对象,1个执行行走对象。
之所以要创建3个对象,主要是考虑到软件工程的分而治之的思想。
另外如果你真是要制作机器人的话
可以做2个系统一个是运动控制系统,一个是avi存储系统,系统间不互联。这样互相不会有干扰,而且容易实现,不会让功能混乱。
在同步对象中实现异步接口
【中文标题】在同步对象中实现异步接口【英文标题】: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 使用上面的示例,我已经有一个实现ILight
的WiredLight
,我刚刚添加了WirelessLight
,它还需要实现ILight
。 (基本上我在 Async Zombie 病毒中)
【参考方案1】:
从同步方法执行异步操作可能真的很危险。没有完美的方法可以做到这一点,而且您可能经常遇到线程饥饿问题的死锁。这不是你想要发现自己的情况。
另一方面,从异步方法同步操作是安全的。当然,你在对调用者撒谎,但这并不是真正的问题,除非他想并行执行你的代码(在这种情况下,他会在注意到问题后简单地添加一个Task.Run
,你也应该在cmets)。在等待完成的任务时,运行时足够智能以优化调用,因此对调用者的性能影响非常小,对于大多数应用程序来说可以忽略不计。
因此,如果您有理由认为您需要在您的接口实现之一中执行异步代码,请不要犹豫,将其标记为异步。对于实际上是同步的实现,返回一个已完成的任务通常是最好的做法:
public Task DoSomethingAsync()
DoSomething();
return Task.CompletedTask;
我建议不要在方法内部使用Task.Run
,因为它通常是不可取的,并且可以在需要时由调用者轻松添加。 .net 中的async
表示该方法可以异步完成,而不是它会很快返回。
【讨论】:
以上是关于如何在一个类中实现异步的主要内容,如果未能解决你的问题,请参考以下文章