c#的async到不是不是异步,它和多线程是什么关系

打野的小妞 2017-08-16 12:45:38
自己想学一下多线程这个东西,用了下Thread,接着在网上看到了async这个东西,说是异步,我自己写了下代码试了一下

static void Main(string[] args)
{
Async3();
for (int i = 0; i < 1000; i++)
{
Console.WriteLine("主线程");
}
Console.ReadLine();
}
static async void Async3()
{
for (int i = 0; i < 1000; i++)
{
Console.WriteLine("异步");

}
}
这里他会先把异步全打印出来才打印主线程,这么看来就不是异步啊,但是按照网上的await用法以后
static async void Async2()
{
// Console.WriteLine("ddd");
await Task.Run(() => { Thread.Sleep(500); Console.WriteLine("bbb"); });
Console.WriteLine("ccc");
}
这里就是先做Main里面的,再来接着做await里面的
想请教下async到底是不是异步,它和多线程是什么关系,一定要和await一起使用吗
...全文
1029 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
Serveetah 2020-01-28
  • 打赏
  • 举报
回复
引用 3 楼 以专业开发人员为伍 的回复:
异步这个字眼儿就是说回调次序是灵活的、不确定的。

由于这个原因,我们其实可以假设它总是跟多线程有密切的和直接的关系,这样去理解它一般不会出大问题。

async/await 语法的作用,是简化了异步回调语法,使得可以用非常类似同步操作的语句来实际编写异步回调。比如我们Main中写代码
Async1(()=>
{
Async2(r=>
{
Async3(r, x=>
{
Console.WriteLine("结果是 {0}", r+x);
});
}
});
这种异步切多线程(子线程)需求流程,我们用 async/await 时就简写为
static void Main(string[] args)
{
Async1();
Console.WriteLine("...............按任意键退出");
Console.ReadKey();
}

static async Task Async1()
{
var r = await Async2();
var x = await Async3(r);
Console.WriteLine("结果是 {0}", r + x);
}

static async Task<int> Async2()
{
await Task.Delay(1000);
return 100;
}

static async Task<int> Async3(int x)
{
await Task.Delay(1000);
return x % 7;
}

这种代码,那么看起来嵌套少了、代码整洁了。

但是要清楚的是,其实这是对人的素质要求提高了。因为对于稍微复杂一点的程序,你要调试跟踪代码 bug,你得懂得 async/await 的原理机制,才可能有调试跟踪的思路,不然如果满脑子还是”顺序、同步“的思路就会在开发中”死得很惨“了。

所以我说,async/await 也是有它双刃剑的一面,容易被一些小白当作高大上的标题党,写出一堆蒙出来的、无法真正分析出来时序流程和测试维护方案的代码。



static void Main(string[] args)
{
Async1();
Console.WriteLine("...............按任意键退出");
Console.ReadKey();
}

static void Async1()
{
Task.Run(delegate
{
var r = Async2();
var x = Async3(r);
Console.WriteLine("结果是 {0}", r + x);
});
}

static int Async2()
{
Thread.Sleep(1000);
return 100;
}

static int Async3(int x)
{
Thread.Sleep(1000);
return x % 7;
}



我想问下,如果这样写,运行的结果是一样的,不使用async/await,似乎更简洁,使用async/await有什么好处呢?
zeng_z 2017-08-16
  • 打赏
  • 举报
回复
1. 是异步的 2. 它使用了线程池技术 3. 搭配一起使用,可以完成Java里面的Futrue模式
ownding 2017-08-16
  • 打赏
  • 举报
回复
1、async/await肯定是异步的。重点在await上,而不在async上。 2、多线程是并发的一种形式,异步也是并发的一种形式。 3、async不一定要跟await一起使用(见下面示例)。但是最好是一起。它们返回Task<T>、Task,也可以void(不推荐)。
static async Task ThrowNotImplementedExceptionAsync()
        {
            throw new NotImplementedException();
        }
  • 打赏
  • 举报
回复
异步这个字眼儿就是说回调次序是灵活的、不确定的。 由于这个原因,我们其实可以假设它总是跟多线程有密切的和直接的关系,这样去理解它一般不会出大问题。 async/await 语法的作用,是简化了异步回调语法,使得可以用非常类似同步操作的语句来实际编写异步回调。比如我们Main中写代码
Async1(()=>
{
     Async2(r=>
    {
        Async3(r, x=>
        {
           Console.WriteLine("结果是 {0}", r+x);
        });
    }
});
这种异步切多线程(子线程)需求流程,我们用 async/await 时就简写为
static void Main(string[] args)
{
    Async1();
    Console.WriteLine("...............按任意键退出");
    Console.ReadKey();
}

static async Task Async1()
{
    var r = await Async2();
    var x = await Async3(r);
    Console.WriteLine("结果是 {0}", r + x);
}

static async Task<int> Async2()
{
    await Task.Delay(1000);
    return 100;
}

static async Task<int> Async3(int x)
{
    await Task.Delay(1000);
    return x % 7;
}
这种代码,那么看起来嵌套少了、代码整洁了。 但是要清楚的是,其实这是对人的素质要求提高了。因为对于稍微复杂一点的程序,你要调试跟踪代码 bug,你得懂得 async/await 的原理机制,才可能有调试跟踪的思路,不然如果满脑子还是”顺序、同步“的思路就会在开发中”死得很惨“了。 所以我说,async/await 也是有它双刃剑的一面,容易被一些小白当作高大上的标题党,写出一堆蒙出来的、无法真正分析出来时序流程和测试维护方案的代码。
  • 打赏
  • 举报
回复
一个编程接口设计为异步的,大多数时候都是为了灵活地处理并发流程需求的,这是明确的!把一些流程放到子线程中并发执行,然后将来才回调、继续处理后续内容,这需要给调用者预先设计异步接口方式。同时我们也可以先如上面例子一样,先把它内部实现为同步顺序操作! 所以这就好像是现有一个文明的法案,然后才有文明的市民。所以我们看到设计为异步方式的调用接口,总是假设它的内部随时会优化、调整、并发的。
  • 打赏
  • 举报
回复
异步是一种语法现象。比如说我写代码
static void Main(string[] args)
{
    Async3(() =>
    {
        Console.WriteLine("Async3完毕,执行了回调");
    });

    Console.WriteLine("...............按任意键退出");
    Console.ReadKey();
}
那么这里只知道 Async3会按照协议而异步回调我注册的 Console.WriteLine 代码,至于说是不是在子线程回调、是不是在Async3完成之后才回调(在 Async3完成之后过一会才回调,也完全可能是注册到主线程去回调),这里并没有说明。 那么只有看懂了 Async3 里边的机制,才知道实际运行时结果。例如
static void Main(string[] args)
{
    Async3(() =>
    {
        Console.WriteLine("Async3完毕,执行了回调");
    });

    Console.WriteLine("...............按任意键退出");
    Console.ReadKey();
}
static void Async3(Action callback)
{
    Console.WriteLine("异步");
    callback();
}
这其实就总是先执行 Async3然后才中Main中其它代码,而如果写
static void Main(string[] args)
{
    Async3(() =>
    {
        Console.WriteLine("Async3完毕,执行了回调");
    });

    Console.WriteLine("...............按任意键退出");
    Console.ReadKey();
}
static void Async3(Action callback)
{
    Task.Run(() =>
    {
        Console.WriteLine("异步");
        callback();
    });
}
这几乎就是总是最后才执行Async3中的代码。 所以,“异步”是一种编程模式,就好像乐视的财务对员工说“你们别为了讨要薪水在这儿绝食抗议了,我有了钱肯定先发给你”,那么财务是真的第一时间发工资还是要等老板转移了资产之后才发工资,只有他自己心里最清楚。但是他表面上做足了“异步接口”了!

110,476

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧