今天在群里,有人问

有几个void返回值的方法,但是我想让这几个方法有执行顺序,要怎么处理,ABCD 四个方法,依次执行,但是这几个方法都是无返回值的

这个问题其实很简单,如果方法是同步方法,直接四个方法连续写就好了,比如:

    static void Main()
{
A();
B();
C();
D();
}

但是如果方法里面包含了耗时操作,那么四个这样写就有问题了,执行顺序就错掉了,我们需要利用callback函数来进行操作,但是本着能不动原方法就不动的理念,我们使用Task的OnCompleted事件(.net framework中可以使用BeginInvoke(callback,null))来做处理

  1. 如果方法有返回值,则使用Func,或者Func<>
  2. 如果方法没有返回值,则使用Action,或者Action<>

1. 无返回值在.net core中使用Task的OnCompleted事件

由于是没有返回值的方法,我们使用

例如

     static void Main()
{
Action action1 = () => {
Thread.Sleep(1000);
Console.WriteLine("action1");
}; Action action2 = () => {
Thread.Sleep(2000);
Console.WriteLine("action2");
}; Action action3 = () => {
Thread.Sleep(3000);
Console.WriteLine("action3");
}; Action action4 = () => {
Thread.Sleep(3000);
Console.WriteLine("action4");
};
Stack st = new Stack();
st.Push(action2);
st.Push(action3);
st.Push(action4); void MyAsynCallback()
{
if (st.Count > 0)
{
var action = (Action)st.Pop();
Task.Run(action).GetAwaiter().OnCompleted(() =>
{
MyAsynCallback();
});
}
}
Task.Run(action1).GetAwaiter().OnCompleted(() =>
{
MyAsynCallback();
});
Console.ReadLine();
//Stack的Pop是先进后出,输出顺序action1 action4 action3 action2
}

我们可以将Stack改成其他的,比如List、Queue等,自行判断是否需要手动弹出action即可

2. 无返回值在.net framework中使用BeginInvoke

     static void Main()
{
Action action1 = () => {
Thread.Sleep(1000);
Console.WriteLine("action1");
}; Action action2 = () => {
Thread.Sleep(2000);
Console.WriteLine("action2");
}; Action action3 = () => {
Thread.Sleep(3000);
Console.WriteLine("action3");
}; Action action4 = () => {
Thread.Sleep(3000);
Console.WriteLine("action4");
};
Stack st = new Stack();
st.Push(action2);
st.Push(action3);
st.Push(action4); void MyAsynCallback(IAsyncResult async)
{
if (st.Count > 0)
{
var action = (Action)st.Pop();
action.BeginInvoke(new AsyncCallback(MyAsynCallback),null);
}
}
action1.BeginInvoke(new AsyncCallback(MyAsynCallback), null);
Console.ReadLine();
//Stack的Pop是先进后出,输出顺序action1 action4 action3 action2
}

3. 有返回值在.net core中使用Task的OnCompleted事件

由于是没有返回值的方法,我们使用

例如

     static void Main()
{
Func<int> func1 = () => {
Thread.Sleep(1000);
Console.WriteLine("func1");
return 1;
}; Func<int> func2 = () => {
Thread.Sleep(2000);
Console.WriteLine("func2");
return 1;
}; Func<int> func3 = () => {
Thread.Sleep(3000);
Console.WriteLine("func3");
return 0;
}; Func<int> func4 = () => {
Thread.Sleep(3000);
Console.WriteLine("func4");
return 1;
};
Stack st = new Stack();
st.Push(func2);
st.Push(func3);
st.Push(func4); void MyAsynCallback(int result)
{
if (st.Count > 0 && result > 0)
{
var action = (Func<int>)st.Pop();
var task1 = Task.Run(action);
task1.GetAwaiter().OnCompleted(() =>
{
MyAsynCallback(task1.Result);
});
}
}
var task = Task.Run(func1); task.GetAwaiter().OnCompleted(() =>
{
MyAsynCallback(task.Result);
});
Console.ReadLine();
//Stack的Pop是先进后出,输出顺序func1 func4 func3 func2
}

4. 有返回值在.net framework中使用BeginInvoke

     delegate int dele_func(int a);
static void Main()
{
Func<int> func1 = () => {
Thread.Sleep(1000);
Console.WriteLine("func1");
return 1;
}; Func<int> func2 = () => {
Thread.Sleep(2000);
Console.WriteLine("func2");
return 1;
}; Func<int> func3 = () => {
Thread.Sleep(3000);
Console.WriteLine("func3");
return 1;
}; Func<int> func4 = () => {
Thread.Sleep(3000);
Console.WriteLine("func4");
return 1;
};
Stack st = new Stack();
st.Push(func2);
st.Push(func3);
st.Push(func4); void MyAsynCallback(IAsyncResult async)
{
dele_func dele_Func2 = (dele_func)async.AsyncState;
int result = dele_Func2.EndInvoke(async);
if (st.Count > 0 && result > 0)
{
var action = (Func<int>)st.Pop();
dele_func dele_Func1 = new dele_func((int a) => { return action.Invoke(); });
IAsyncResult asyncResult1 = dele_Func1.BeginInvoke(0, new AsyncCallback(MyAsynCallback), dele_Func1);
}
}
dele_func dele_Func = new dele_func((int a) => { return func1.Invoke(); });
IAsyncResult asyncResult = dele_Func.BeginInvoke(0, new AsyncCallback(MyAsynCallback), dele_Func);
Console.ReadLine();
//Stack的Pop是先进后出,输出顺序func1 func4 func3 func2
}

有返回值时,可以根据result的判断,来判断是否继续往下执行

如有问题,欢迎指正

ABCD四个顺序执行方法,拓展性延申的更多相关文章

  1. c#线程顺序执行

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...

  2. Node.js的那些坑——如何让异步并发方法同步顺序执行(for循环+异步操作)

    1 前言 nodejs的回调,有时候真的是让人又爱又恨的,当需要用for循环把数据依次存入数据库,但是如果使用正常的for循环,永远都是最后一次值的记录,根本不符合要求. 解决此方案有几种,例如闭包( ...

  3. 三个线程T1,T2,T3.保证顺序执行的三种方法

    经常看见面试题:有三个线程T1,T2,T3,有什么方法可以确保它们按顺序执行.今天手写测试了一下,下面贴出目前想到的3种实现方式 说明:这里在线程中我都用到了sleep方法,目的是更容易发现问题.之前 ...

  4. ajax异步导致js方法顺序执行不了

    js两个方法调用的顺序,有时候是这样的 f1(); f2(); 本来是先执行f1的,但是如果f1里面进行ajax异步    async:true,那么可能会先执行f2,如果想要顺序执行,那么就把异步设 ...

  5. c#数据四种执行方法(ExecuteNonQuery)-----转载

    c#数据四种执行方法(ExecuteNonQuery)   1.使用ExecuteReader()操作数据库 2.使用ExecuteNonQuery()操作数据库 3.使用ExecuteScalar( ...

  6. 使用定时器判断确保某个标签有值才执行方法, 控制js代码执行先后顺序

    使用定时器判断确保某个标签有值才执行方法: var wait = setInterval(function(){ var diqu = $("#diqu").val(); //确保 ...

  7. 更优雅的方式: JavaScript 中顺序执行异步函数

    火于异步 1995年,当时最流行的浏览器--网景中开始运行 JavaScript (最初称为 LiveScript). 1996年,微软发布了 JScript 兼容 JavaScript.随着网景.微 ...

  8. {Django基础九之中间件} 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证

    Django基础九之中间件 本节目录 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证 六 xxx 七 xxx 八 xxx 一 前戏 我们在前面的课程中已经学会了 ...

  9. js的并行加载以及顺序执行

    重新温习了下这段内容,发现各个浏览器的兼容性真的是搞大了头,处理起来很是麻烦. 现在现总结下并行加载多个js的方法: 1,对于动态createElement('script')的方式,对所有浏览器都是 ...

随机推荐

  1. Nginx_配置文件nginx.conf配置详解

    user nginx nginx ; # Nginx用户及组:用户 组.window下不指定 worker_processes 8; # 工作进程:数目.根据硬件调整,通常等于CPU数量或者2倍于CP ...

  2. java POJO中 Integer 和 int 的不同,用int还是用Integer

    https://www.jianshu.com/p/ff535284916f [int和Integer的区别] int是java提供的8种原始类型之一,java为每个原始类型提供了封装类,Intege ...

  3. Python之路 - Day4 - Python基础4 (新版)

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需 ...

  4. 简单的Dos 命令

    1.1.如何操作DOS命令 开始---运行---输入cmd--回车 或者 Win + R ---运行---输入cmd--回车 1.2.基本命令 1. 命令:color f0 帮助:color ? 作用 ...

  5. Vulnhub系列:Tomato(文件包含getshell)

    这个靶机挺有意思,它是通过文件包含漏洞进行的getshell,主要姿势是将含有一句话木马的内容记录到ssh的登录日志中,然后利用文件包含漏洞进行包含,从而拿到shell 0x01 靶机信息 靶机:To ...

  6. 基于Jenkins+Maven+Gitea+Nexus从0到1搭建CICD环境

    在传统的单体软件架构中,软件开发.测试.运维都是以单个进程为单位. 当拆分成微服务之后,单个应用可以被拆分成多个微服务,比如用户系统,可以拆分成基本信息管理.积分管理.订单管理.用户信息管理.合同管理 ...

  7. CTF-sql-sql约束注入

    create table user( id int not null auto_increment, username varchar(30) not null, password varchar(3 ...

  8. 《剑指offer》面试题05. 替换空格

    问题描述 请实现一个函数,把字符串 s 中的每个空格替换成"%20". 示例 1: 输入:s = "We are happy." 输出:"We%20a ...

  9. [开发笔记usbTOcan]需求获取与系统需求分析

    简介 一直一以来都是站在实现某个模块功能的角度去做软件开发,没有尝试过站在系统的层面去做开发.最近正好不忙,觉得是时候以系统工程师的视角,去开发一个完整的系统.接下来的几篇文章,我会记录一个USB转C ...

  10. java接口概述及特点

    1 package face_09; 2 3 4 5 6 abstract class AbsDemo{ 7 abstract void show1(); 8 abstract void show2( ...