多线程合集(三)---异步的那些事之自定义AsyncTaskMethodBuilder

引言    

    之前在上一篇文章中多线程合集(二)---异步的那些事,async和await原理抛析,我们从源码去分析了async和await如何运行,以及将编译后的IL代码写成了c#代码,以及实现自定义的Awaiter,自定义异步状态机同时将本系列的第一篇文章的自定义TaskScheduler和自定义的Awaiter结合起来,将代码跑了起来,而在c#10之后,我们可以实现自定义的异步生成器,在上一篇文章中,我们将编译后的代码还原成了c#代码,其中就有用到了一个AsyncTaskMethodBuilder的类,搁以前我们只能使用编译器编译之后的AsyncTaskMethodBuilder,现在我们已经可以自定义了,如果再加上上一章节的自定义状态机,加调度,可能会更好玩一些,接下来就为大家奉上代码。

代码

   总共没有多少代码,只是为了简单的实现自定义的AsyncTaskMethodBuilder, 当然可能后续某位哥哥会用到将这些知识点串联起来使用呢,可以看到,下面我们继承了Task,实现了MyTask,此处演示效果,仅仅实现了一个构造函数以及一个GetAwaiter的方法,然后上面就是我们测试调用的Test方法,为什么还需要new一个新的GetAwaiter呢,如果我们使用默认的TaskAwaiter,那你在Main方法await tes.Test的时候就会卡死的至于原因,就是await之后的代码等待结果是等待await之后的返回到上一层也就是说await后面的主动推结果,但是卡死是因为上一层却主动找我要结果导致的卡死,导致我推不过去,上一层也找不到结果,此处我没有具体分析,但是我的猜测是这样,看官们可以自己尝试一下,将MyTask的GetAwaiter注释,使用默认的TaskAwaiter,然后调用Test方法,如果是await的时候肯定卡死,但是如果Task同步运行,也就是RunSynchronously这种方式运行,然后直接.Result,就可以获取到结果,刚好可以验证我上面的猜测,同一上下文了,不需要他主动推,但我可以主动获取,

   然后在往下面走就是我们自定义的一个Awaiter,实现接口后,构造函数的Func是我们返回结果的委托,这个结果是GetResult之后的结果值,OnCompleted方法和下面的Unsafe都是去推进状态机告诉已经完了异步的,上一章节说过这两个方法的参数Action,实际上就是状态机的MoveNext方法,最后就到了我们的自定义Builder实现,只需要遵循如下条件,官网列出的条件,既可以实现一个自定义的Builder,

// See http://aka.ms/new-console-template for more information
using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
public class Program
{
    static async Task Main(string[] args)
    {

        var tes = new TestAsync();
        var task =await tes.Test();
        Console.ReadKey();
    }
}
public class TestAsync
{
    public async MyTask<int> Test()
    { 
        await MyTask<int>.Delay(1);
        return 100;
    }
}

[AsyncMethodBuilder(typeof(MyTaskBuilder<>))]
public class MyTask<T> : Task<T> where T : notnull
{
    public MyTask(Func<T> action) : base(action) 
    {
        Action = action;
    }

    public Task<T> Task { get; }
    public Func<T> Action { get; }

    //
    // 摘要:
    //     Gets an awaiter used to await this System.Threading.Tasks.Task`1.
    //
    // 返回结果:
    //     An awaiter instance.
    public new CustomAwaiter<T> GetAwaiter()
    { 
       var awaiter=new CustomAwaiter<T>(Action);
        return awaiter;
    }

    // 添加构造函数和其他功能代码
}
public class CustomAwaiter<T> : ICriticalNotifyCompletion
{
    public CustomAwaiter(Func<T> func)
    {
        Func = func;
    }
    public bool IsCompleted { get; set; }
    public Func<T> Func { get; }

    public void OnCompleted(Action continuation)
    {
        continuation();
        IsCompleted = true;
    }

    public void UnsafeOnCompleted(Action continuation)
    {
        continuation();
        IsCompleted = true;
    }
    public T GetResult()
    {
        return Func() ;
    }
}

public class MyTaskBuilder<T> where T:notnull
{
    private readonly AsyncTaskMethodBuilder<T> _builder = new AsyncTaskMethodBuilder<T>();
    private T Value;
    public static MyTaskBuilder<T> Create()
    {
        return new MyTaskBuilder<T>();
    }

    public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
    {
        _builder.Start(ref stateMachine);
    }

    public void SetStateMachine(IAsyncStateMachine stateMachine)
    {
        _builder.SetStateMachine(stateMachine);
    }

    public void SetResult(T val)
    {
        Value = val;
        _builder.SetResult(val);
    }

    public void SetException(Exception exception)
    {
        _builder.SetException(exception);
    }
    public MyTask<T> Task
    {
        get
        {
            return new MyTask<T>(new Func<T>(() => Value));
        }
    }

    public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
        where TAwaiter : INotifyCompletion
        where TStateMachine : IAsyncStateMachine
    {
        _builder.AwaitOnCompleted(ref awaiter, ref stateMachine);
    }

    public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
        where TAwaiter : ICriticalNotifyCompletion
        where TStateMachine : IAsyncStateMachine
    {
        _builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
    }
}
public class StateMachine : IAsyncStateMachine
{
    public StateMachine()
    {
        
    }
    public void MoveNext()
    {
        throw new NotImplementedException();
    }

    public void SetStateMachine(IAsyncStateMachine stateMachine)
    {
        throw new NotImplementedException();
    }
}

自定义Builder的条件

    自定义AsyncTaskMethodBuilder,需要满足一下条件,即你定义的这个Builder类需要有Create方法,Task的属性,SetException,设置异常的,SetResult设置结果的,以及一个Start的方法,同时在需要指定异步Builder的类或者方法使用AsyncMethodBuilderArrtibute特性,里面需要的参数就是你自定义Builder的type,即要么在MyTask类上面使用此特性,也可以直接在Test方法上面添加此特性都可以实现自定义Builder,当然了此处有个扩展就是你可以参考上一章节的自定义状态机,调度器,awaiter,自己手动实现编译器编译之后的代码,也就是下面这一段,当然了,内功深厚自己借此实现一个简单的异步也是没问题的,自己实现Task,类似我如上,继承Task,然后借助线程上下文等一些api,去实现一个自己的异步也不是什么难得事情,总之,此片文章实际上可能业务中会用不到,但是结合前几篇,也可以更好的理解async和await了。

    CustomAsyncStateMechine customAsyncStateMechine = new CustomAsyncStateMechine();
            customAsyncStateMechine.builder = AsyncTaskMethodBuilder<string>.Create();
            customAsyncStateMechine.State = -1;
            customAsyncStateMechine.builder.Start(ref customAsyncStateMechine);
            return customAsyncStateMechine.builder.Task;

 

        

结束

    今天水的一篇博客就到这里了,因为大家能更好的理解async和await,能够将这些自定义的东西玩出花来,哈哈,关于async和await以及线程方面,感兴趣的可以看看我之前的文章。

 

本文转载于网络 如有侵权请联系删除

相关文章

  • 【Flutter】评级对话框组件

    F「lutter」是一个免费和开源的项目,由Google创建并维护,是我们喜欢Flutter的原因之一。Flutter提供了漂亮的预构建组件,这些组件在flutter中被称为Widget。扑朔迷离的一切都是小部件!向用户显示一些知识是一个了不起的想法,这是我们使用对话框的最基本的想法。在Flutter这个惊人的UI工具包中,我们有几种不同的方法来构建对话框。在在本博客中,我们将探讨「Flutter中」的“「评级对话框”」。我们将看到如何使用flutter应用程序中的「rating_dialog」包来实现美观的评级对话框演示程序并进行自定义。pub地址:https://pub.dev/packages/rating_dialog评分对话框评分对话框是Flutter出色且适应性强的星级评分对话框包!它支持flutter支持的所有阶段。这个库是最好的,因为它伴随着星级评价和联系,甚至可以滑动评级并发光以进行星级评价。之所以命名为“等级”对话框,是因为该库将识别您在颤动的星形图标上做出的手势以提供等级。评级对话框的一些属性:**message:**此属性用于对话框的消息/描述文本。**rati

  • Tailwind CSS (可能)是名过其实的

    TailwindCSS是一个工具集CSS框架,网上很多文章已对其有详尽的介绍。本文不是官方文档的复述,也不是系列优点的罗列,作者Gerard会从另一个角度出发,在尽力保持客观的前提下,立足于实际开发的场景,指出TailwindCSS存在的一些问题。事实上,除了文中提及的,TailwindCSS还存在着不少缺点,比如对高度定制化的支持程度不足、记忆大量预定义类名带来的心智负担等。友情提醒,你不一定会赞同这篇文章的看法,因为我们的看法会受到自身认知和使用体验的影响,但更重要的是可能是作者对新兴技术的态度,用他的原话说,就是:“Wheneveryoneisshoutingthatit’sawesome,it’susuallyagoodmomenttositdownandhaveagoodlookatit”下面正文开始。原文地址:TailwindCSSIs(Probably)Overhyped原文作者:GerardvanderPut译者:Chor引言在过去的两年间,TailwindCSS广受青睐(从每周30K的下载量到如今的600K)。毫无疑问,这个流行的实用优先CSS框架具备诸多优点。很可能

  • R练习50题 - 第五期

    习题预览小编最近实在有很多事情要做,抓住了空档就马上更新了!继续看题!16.上证50、沪深300、中证500指数成分股中,沪股和深股各有多少?17.上证50、沪深300、中证500指数成分股中,行业分布如何?18.每天上证50、沪深300、中证500指数成分股的总成交额各是多少?19.上证50、沪深300、中证500指数日收益率的历史波动率是多少?20.上证50、沪深300、中证500指数日收益率的相关系数矩阵?21.上证50、沪深300、去除上证50的沪深300指数日收益率的相关系数矩阵?习题1616.上证50、沪深300、中证500指数成分股中,沪股和深股各有多少?代码及解析:data[,melt(.SD,measure.vars=patterns("index"),variable.name="index_name") ][value>0,.(stkcd_amount=uniqueN(symbol)),by=.(index_name,date,type=ifelse(str_detect(symbol,"SH"),

  • python 安装教程之Pycharm安装及配置字体主题,换行,自动更新

    下载下面提供两种下载地址,官网地址一般为最新的,网盘地址会定期更新,但是不保证一定是最新的官网下载地址:https://www.jetbrains.com/pycharm/download/download-thanks.html?platform=windows百度网盘地址:https://pan.baidu.com/s/1EhtY5PD3XagJ-nTw8IX8Vw提取码:z8ej安装1、双击exe安装2、自定义安装路径2、配置3、添加到开始菜单里可以选择放在其他文件夹(不推荐,除非是同家公司的其他应用)4、重启更新需要重启更新配置5、重启完成可以在开始菜单里找到pycharm,双击启动 导入settings配置,我们这里选择不导入同意协议发送数据,帮助官方团队改进产品,选哪个都行选择哪种主题都行,后续可以在设置里面更改选择下载插件(模拟Vim编辑器,markdown文档,r语言支持,AWS工具包)激活码激活激活完成后就可以使用啦PS 一些简单的配置 在右下角打开设置字体settings—Editor—Fon主题settings—Editor—ColorScheme关闭自动更新se

  • APT29分析报告

    简介APT29是威胁组织,已被归于俄罗斯政府情报组织,APT29至少从2008年开始运作,具有YTTRIUM、TheDukes、CozyDuke、CozyBear、OfficeMonkeys等别名。主要攻击目标为美国和东欧的一些国家。攻击目的是为了获取国家机密和相关政治利益,包括但不限于政党内机密文件,操控选举等。与APT28,同属于俄罗斯政府的APT28相互独立,但在某种程度上会联合行动。APT29是东欧地区最为活跃的APT组织之一。该APT的许多组件均通过伪造的Intel和AMD数字证书进行签名。活动分析2014年3月,位于华盛顿特区的一家私人研究机构的内部网络被发现感染了Cozyduke(Trojan.Cozer)。然后,CozyBear发起了一项鱼叉式钓鱼邮件攻击行动,试图诱使受害者点击内容为办公室猴子的Flash视频,其中也包含恶意可执行文件。到7月,该小组已经攻陷了部分了政府网络,并控制受Cozyduke病毒感染的系统将Miniduke安装到了被攻陷的网络上。同年夏天,荷兰通用情报和安全局的特工反向渗透了CozyBear,发现该组织将美国民主党,美国国务院,白宫作为目标。F

  • 在Kubernetes上运行有状态应用:从StatefulSet到Operator

    一开始Kubernetes只是被设计用来运行无状态应用,直到在1.5版本中才添加了StatefulSet控制器用于支持有状态应用,但它直到1.9版本才正式可用。本文将介绍有状态和无状态应用,一个通过K8SStatefulSet来编排有状态应用的示例,以及当前有状态应用容器化现状及将来的发展趋势。1.有状态应用和无状态应用无状态应用(StatelessApplication)是指应用不会在会话中保存下次会话所需要的客户端数据。每一个会话都像首次执行一样,不会依赖之前的数据进行响应。有状态的应用(StatefulApplication)是指应用会在会话中保存客户端的数据,并在客户端下一次的请求中来使用那些数据。 以服务器端组件为例,判断它是有状态的还是无状态的,其依据是两个来自相同发起者的请求在服务器端是否具备上下文关系。如果是有状态的,那么服务器端一般都要保存请求的相关信息,每个请求可以使用以前的请求信息。而如果是无状态的,其处理的过程必须全部来自于请求所携带的信息,以及其他服务器端自身所保存的、并且可以被所有请求所使用的公共信息。最著名的无状态的服务器应用是WEB服务器。每次HTTP请

  • 峰度与偏度(python)

    偏度和峰度是描述数据分布时两个常用的概念,用来描述数据分布与正态分布的偏离程度。本次推送将简要介绍其相关意义,及通过python中pandas包实现相关计算。偏度与峰度偏度(Skewness) 用来描述数据分布的对称性,正态分布的偏度为0。计算数据样本的偏度,当偏度<0时,称为负偏,数据出现左侧长尾;当偏度>0时,称为正偏,数据出现右侧长尾;当偏度为0时,表示数据相对均匀的分布在平均值两侧,不一定是绝对的对称分布,此时要与正态分布偏度为0的情况进行区分。 当偏度绝对值过大时,长尾的一侧出现极端值的可能性较高。峰度(Kurtosis) 用来描述数据分布陡峭或是平滑的情况。正态分布的峰度为3,峰度越大,代表分布越陡峭,尾部越厚;峰度越小,分布越平滑。很多情况下,为方便计算,将峰度值-3,因此正态分布的峰度变为0,方便比较。 在方差相同的情况下,峰度越大,存在极端值的可能性越高。python实现用python中的pandas包可以便捷的计算出峰度与偏度。载入相关包,生成满足正态分布的点,并绘制出其分布图像。importpandasaspd importnumpyasnp impo

  • 编程大师访谈录

    什么是编程?人们对此一直各持己见。有人说它是科学,有人说它是艺术,还有人称之为技能或手艺。我认为这三方面兼而有之。我们喜欢说它蕴含大量艺术成分,但是我们都知道它里面更多的是科学。我觉得代码清单带给人的愉快同整洁的家差不多。你一眼就能分辨出家里是杂乱无章(比如垃圾和没洗的碟子到处乱扔)还是整洁如新。编程的第一步是想象。就是要在脑海中对来龙去脉有极为清晰的把握。在这个初始阶段,我会使用纸和铅笔。我只是信手涂鸦,并不写代码。我也许会画些方框或箭头,但基本上只是涂鸦,因为真正的想法在我脑海里。我喜欢想象那些有待维护的结构,那些结构代表着我想编码的真实世界。一旦这个结构考虑得相当严谨和明确,我便开始写代码。我会坐到终端前,或者换在以前的话,就会拿张白纸,开始写代码。这相当容易。我只要把头脑中的想法变换成代码写下来,我知道结果应该是什么样的。大部分代码会水到渠成,不过我维护的那些数据结构才是关键。我会先想好数据结构,并在整个编码过程中将它们牢记于心。假装每时每刻都很快乐是做作。就像运动员所说的:“要是没受伤的话,肯定是你还不够努力。”代码的效率还会随着开发同一个程序的人员数量的增加而有所降低。最高

  • 接前两篇--laravel写api

    上一篇试着用migrate操作了一下数据库;创建了一个表;这次用php写一个借口,前端通过这两个借口,对数据库进行操作;先创建一个用户表 默认创建的不是我们想要的,回滚一下2.方便简单,在生成的文件中就只加两个字段,username与sex;3.之后运行phpartisanmigrate创建之后,查看这个表结构就是这样的--------分割线--------4.选择创建一个model文件通过命令创建;原本app目录下自动生成了一个用户模型,删除一下就是;原本生成那个需要各种验证,下次谈;5.生成之后,可以不动,先打开route文件夹下的web文件;添加两个路由,相当于是api了;分别是/api与/find执行的逻辑如下图6.之后打开模型文件User.php添加两个方法,对应刚才那个路由需要的逻辑;如下图一个是添加数据一个是查找数据7.启动服务,进行请求返回ok,说明数据插入成功;改变参数,多请求几次,数据库就多几条;这就是通过前端插入数据之后的表8.可以试试查询接口;都没问题;----分割线-----如果请求的时候有报错,说数据库无法连接什么检查一下配置文件,清除一下缓存检查配置文件

  • MongoDB 分片集群技术

     1.1MongoDB复制集简介  一组Mongodb复制集,就是一组mongod进程,这些进程维护同一个数据集合。复制集提供了数据冗余和高等级的可靠性,这是生产部署的基础。1.1.1复制集的目的  保证数据在生产部署时的冗余和可靠性,通过在不同的机器上保存副本来保证数据的不会因为单点损坏而丢失。能够随时应对数据丢失、机器损坏带来的风险。  换一句话来说,还能提高读取能力,用户的读取服务器和写入服务器在不同的地方,而且,由不同的服务器为不同的用户提供服务,提高整个系统的负载。1.1.2简单介绍  一组复制集就是一组mongod实例掌管同一个数据集,实例可以在不同的机器上面。实例中包含一个主导,接受客户端所有的写入操作,其他都是副本实例,从主服务器上获得数据并保持同步。  主服务器很重要,包含了所有的改变操作(写)的日志。但是副本服务器集群包含有所有的主服务器数据,因此当主服务器挂掉了,就会在副本服务器上重新选取一个成为主服务器。  每个复制集还有一个仲裁者,仲裁者不存储数据,只是负责通过心跳包来确认集群中集合的数量,并在主服务器选举的时候作为仲裁决定结果。1.2复制的基本架构  基本的

  • 一款高度可定制的WiFi钓鱼工具 – WiFiPhisher

    工具简介WiFiPhisher是一款高度可定制的WiFi钓鱼攻击工具,它可以对具体的WiFI客户端进行攻击,例如获取用户凭证或感染恶意软件。与其他攻击不同的是,WiFiPhisher并不会进行爆破攻击,因为它主要使用的是社会工程学技术,而社工技术也是攻击者窃取用户凭证的一种简单且有效的方法。注:WiFiPhisher需要在KaliLinux系统上运行,使用开源GPL许可证。工作机制利用EvilTwin(双面恶魔)攻击实现了中间人攻击之后,WiFiPhisher会将目标用户所有的HTTP请求重定向至一个由攻击者控制的钓鱼页面。从用户的角度来看,这种攻击主要由以下三个阶段组成:1.用户无法接入自己的无线网络接入点。因为WiFiPhisher会劫持目标范围内的所有无线网络接入点,并通过劫持请求数据包来阻止用户访问接入点。 2.用户会接入一个流氓热点。WiFiPhisher会扫描范围内的无线接入点,复制这些接入点的设置信息,然后利用这些配置来创建一个流氓热点,最后欺骗用户连接这个流氓热点。 3.用户会被重定向至一个高度定制化的钓鱼页面。WiFiPhisher会搭建一个小型的Web服务器,并响应

  • 渗透测试系统BackBox Linux 4.1发布

    BackBox是基于Ubuntu的Linux发行版,它是一款用于网络渗透测试及安全评估的操作系统。新版本包括Linux3.13内核,EFI模式,匿名模式,LVM+磁盘加密程序,隐私的补充和armhfDebian软件包。 ISO镜像(32位和64位)可从以下位置下载: http://www.backbox.org/downloads 新版本主要更新: 预装Linux3.13 新版Ubuntu14.04 包含LVM和全盘加密选项 Thunar方便自定义操作 RAMwipeatshutdown/reboot 系统改进 上游组建 错误更正 性能提升 改进匿名模式 倾向ARM架构(armhfDebian软件包) 向BackBox云平台演进 新的安全工具复制 系统要求 32位或64位处理器 512MB的系统内存(RAM) 6GB的磁盘空间用于安装 图形卡能够×600分辨率800 DVD-ROM驱动器或USB端口(2GB)复制 升级说明 从以前的版本升级(配电箱v.4.0)遵循这些指示: 安装命令 sudoapt-getupdate sudoapt-getdist-upgrade sudoapt-g

  • 死磕Spring之AOP篇 - Spring AOP自动代理(三)创建代理对象

    该系列文章是本人在学习Spring的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释Spring源码分析GitHub地址进行阅读。 Spring版本:5.1.14.RELEASE 在开始阅读SpringAOP源码之前,需要对SpringIoC有一定的了解,可查看我的《死磕Spring之IoC篇-文章导读》这一系列文章 了解AOP相关术语,可先查看《SpringAOP常见面试题)》这篇文章 该系列其他文章请查看:《死磕Spring之AOP篇-文章导读》 在前面的《SpringAOP自动代理(一)入口》文章中,分析了SpringAOP自动代理的入口是AbstractAutoProxyCreator对象,其中自动代理的过程主要分为下面两步: 筛选出能够应用于当前Bean的Advisor 找到了合适Advisor则创建一个代理对象,JDK动态代理或者CGLIB动态代理 上一篇《SpringAOP自动代理(二)筛选合适的通知器》文章分析了上面第1步的处理过程,先去解析出当前IoC容器所有Advisor对象,包括Advisor类型的Bean和从@AspectJ注

  • 【NetDevOps】新一代网工需要了解的那点事儿---云计算中的网络虚拟化(一)

    这篇文章本应该在2018年更详细的记录在《dockerbyF0rGeEk》中,由于那本书正好写到网络章节时出了点状况所以没有继续写下去。。。?还是那句老话:出来混早晚都得还??? 本文篇幅较长虽有目录,为方便阅读特将本文按章节拆成几个部分: 【NetDevOps】新一代网工需要了解的那点事儿(一)---网络虚拟化 【NetDevOps】新一代网工需要了解的那点事儿(二)---veth-pair 【NetDevOps】新一代网工需要了解的那点事儿(三)---LinuxBridge 【NetDevOps】新一代网工需要了解的那点事儿(四)---tun/tap 【NetDevOps】新一代网工需要了解的那点事儿(五)---iptables 【NetDevOps】新一代网工需要了解的那点事儿(六)---VTI 【NetDevOps】新一代网工需要了解的那点事儿(七)---VXLAN 【NetDevOps】新一代网工需要了解的那点事儿(八)---Macvlan 目录1.网络虚拟化1.1传统网络虚拟化1.2Linux中网络结构1.3Linuxnetworknamespace1.3.1netns各参

  • 算法效率 简单的增长率 参照

    1、 时间复杂度(TimeComplexity)        一般情况下,算法中的基本操作重复执行次数是问题规模n的某个函数f(n),算法的时间度量记作:            T(n)=O(f(n))       它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称做算法的逐渐时间复杂度,简称时间复杂度。                          在下列的三个程序中        (a) x=0          (b)&n

  • 夺命雷公狗—JAVA---007---源文件与类名的常见问题

    1,源文件名最好与类名相同,以便后期更好的进行维护       2,源文件与类名不一致,是可以的,代码如下所示:   然后我们过来进行编译: 编译后文件夹内就会将源文件里面的类都使用单个文件的方式进行编译出来了,如上图所示~ ~!   然后我们去运行Hello2 类,即可正常进行运行,如下所示:         3,如果源文件中某个类是public,那么必须要与源文件名相同,不然就会出现报错,使用一源文件只会存在一个public类       4,一个源文件中可以存在多个类,但是在编译后悔出现多个  .class  文件,每个  .class 的名字就是源文件中存在的类名         小结: 日常开发中,一个 .java  文件,只写一个类,除非有内部类 源文件名基本都是和类名一致的,以便后期更好

  • Sql 注入----学习笔记

    先了解下CRLF,CRLF常用在分隔符之间,CR是carriageretum(ASCII13,\r)LF是LineFeed(ASCII10,\n), \r\n这两个字符类似于回车是用于换行的,因此该漏洞可能会导致程序原有的语义被改变 如: defhelloWorld(name): open('test','a').write("Yournameis%s\n"%name)复制 假设传入的参数是"coder",内容应为   "Yournameiscoder"复制   但如果没有处理好用户的输入,攻击者输入类似的代码时就会产生CRLF注入 "coder\nMynameissuperman." "Yournameiscoder" "Mynameissuperman."复制  

  • 杜教筛之逆运算2

    有了杜教筛的式子我们可以干很多事 \[\sum_{i=1}^nf*g(i)=\sum_{i=1}^nf(i)\sum_{j=1}^{\lfloor\frac{n}{i}\rfloor}g(j) \]对于这种两种形式的式子可以用杜教筛式子秒杀 \[1.\sum_{i=1}^n\lfloor\frac{n}{i}\rfloorf(i)\\ 2.\sum_{i=1}^n\lfloor\frac{n}{i}\rfloor^2f(i) \]第一种式子 将杜教筛中\(g()\)特殊化为\(I():I(x)=1\)得 \[\sum_{i=1}^n\lfloor\frac{n}{i}\rfloorf(i)=\sum_{i=1}^nI*f(i) \]第二种式子 给\(f()\)卷上\(id():id(x)=x\)得 \[\begin{align} \sum_{i=1}^nid*f(i)&=\sum_{i=1}^nf(i)\sum_{j=1}^{\lfloor\frac{n}{i}\rfloor}id(j)\\ &=\sum_{i=1}^nf(i)\frac{\lfloor\frac{n}

  • Navicat for MySQL 快捷键

      ctrl+q            打开查询窗口   ctrl+/            注释sql语句   ctrl+shift +/     解除注释   ctrl+r            运行查询窗口的sql语句   ctrl+shift+r      只运行选中的sql语句   F6         

  • 移动端Ios 不能使用audio 自带的canplay事件来获取音频的总时长

      关于Vue使用Audio的文章可以参考 https://blog.csdn.net/weixin_33695450/article/details/91462679   我使用的时候出现一个问题 发现IOS在进入页面时并不能获取到duration属性 也就是并不能获取总时长,但是点开播放之后就可以获取到,百度后发现苹果开发者平台上有说明 https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/AudioandVideoTagBasics/AudioandVideoTagBasics.html      意思大概就是在Safari5.0及更高版本中支持preload属性。iOS上的Safari从不预加载,所以找到了问题所在 解决方法如下 mounted(){ varmusicDom=$('#audio')[0]; letthat=this musicDom.load();

  • redux源码学习笔记 - applyMiddleware

    在创建store时,createStore(reducer,preloadedState,enhancer),除了reducer函数,初始状态,还可以传入enhancer。这个enhancer在createStore的源码中是这样使用的 returnenhancer(createStore)(reducer,preloadedState) 复制 它可以接受createStore方法并进行自定义改装,然后再使用改装后的方法创建仓库。 而redux官方提供的enhancer就只有applyMiddleware。 applyMiddleware(...middlewares) applyMiddleware的主要功能是改写createStore中的dispatch方法,并且可以将多个middleware组合到一起,形式链式的调用,前后互不影响。这样要求middleware必须遵循一定的格式。({getState,dispatch})=>next=>action=>{} applyMiddleware的实现 exportdefaultfunctionapplyMiddlewa

相关推荐

推荐阅读