跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 为什么要干掉那些喜欢卖弄细枝末节的家伙.
未分類
26 5 月 2020

为什么要干掉那些喜欢卖弄细枝末节的家伙.

为什么要干掉那些喜欢卖弄细枝末节的家伙.

資深大佬 : damingxing 0

老夫最近又再看叛徒丢下的一些破代码:

比如有一句话:
await DoAsync();
这样做挺好的,也好理解.

然后那个叛徒偏偏要在某处丢下这么一句:
_ = DoAsync();

喵了个咪,老夫一不小心就被带到沟里,还查半天这个怎么运作的,怕有坑.
就算了解了,对项目有毛线关系.

直接 await !

不好好做项目整天把时间纠结在这种问题上有意义吗. 这种卖弄小技术的人真是可恶啊.

大佬有話說 (100)

  • 資深大佬 : PerFectTime

    哈哈哈,可能是做一份只有自己看得懂的代码就不会被裁?

  • 主 資深大佬 : damingxing

    @PerFectTime 股东之一,负责核心技术,我们替他做脏活累活,他折腾无聊的东西.

  • 資深大佬 : DivineRapierH

    他是在致敬 lodash 吧

  • 主 資深大佬 : damingxing

    @DivineRapierH 不了解。

  • 主 資深大佬 : damingxing

    为了免得激起一些人的敏感神经,下沉此帖。

  • 資深大佬 : nannanziyu

    1,后续没有动作,可以不 await
    相当于异步方法放弃回调
    2,调用非 void 方法,隐式放弃返回结果,IDE 会有 warning,表现为绿色波浪线,所以加个 _=,显示放弃返回

  • 主 資深大佬 : damingxing

    @nannanziyu 有 Async 结尾的函数就用异步调用,就跟命名法则一样的道理。这种问题不在于编译器能不能通过,而在于写程序不是用来炫技的,而是用来解决问题的。

  • 資深大佬 : nannanziyu

    @damingxing 这两个和技没有任何关系,是基本用法

  • 主 資深大佬 : damingxing

    @nannanziyu 微软官方建议的就是所有 Async 结尾的函数都用异步调用。这个问题虽然看起来小,但是所有炫技的人都是这么想的。不要杠了行不。

  • 主 資深大佬 : damingxing

    写成表示异步的函数,就用异步调用,简单规则,无任何累赘之处。
    写成表示异步的函数,偏偏要用同步调用,复杂化规则,典型的简单问题复杂化。

  • 主 資深大佬 : damingxing

    解释的方法无非就是其实这里还是异步调用的,直接打板子。

  • 資深大佬 : nannanziyu

    @damingxing
    1,是的,async/await 只是个无栈协程的语法糖
    并不是不写 await 就是同步调用
    2,这种异步方法并不是看是不是 async 结尾,而是看返回结果是不是 task/task<T>
    3,不是 task 方法就要加 await,这和炫技不炫技没有任何关系,这取决于需要要做什么

    比如发个 log 日志到服务器,方法是 task SendLogAsync(),因为有网络操作,执行时间是 1 秒

    那么下面代码:
    DoA()
    SendLogAsync()
    DoB()

    这段不用 await,表示 DoB()不需要等待 SendLogAsync()做完,也就是 DoA 后不需要等待 1 秒,而是直接 DoB

    而下面代码:
    DoA()
    await SendLogAsync()
    DoB()

    这段加了 await,表示 DoB()需要等待 SendLogAsync()做完,也就是要 DoA 后等待大约一秒后才 DoB

  • 主 資深大佬 : damingxing

    @nannanziyu 炫技就是你这么想问题的.本来是个规范问题,偏偏还要引出一堆别的东西,浪费时间.

    你举的这个例子,首先就应该把 SendLogAsync()这个函数的 Async 去掉,变成 SendLog(),然后再用
    DoA()
    SendLog() => 在这里面怎么搞随便你,总之快点返回就行了.
    DoB()

    实际项目中一会要 await, 一会儿又要迅速返回,那多半是设计逻辑就有问题.
    劝你别杠了.

  • 主 資深大佬 : damingxing

    我对 c#没那么熟,不过大概会这样做这样一个封装.
    void SendLog()
    {
    Task.Run(()=> { await SendLogAsync(); });
    }

  • 資深大佬 : nannanziyu

    @damingxing
    1,知道你对 c#不熟,不过没关系,谁都有新手的时候
    2,从来没有 `*Async() 方法就必须 await 的` 规范
    dotnet core 源代码里到处都是直接调用而不用 await,随便举个例子
    https://github.com/dotnet/aspnetcore/blob/master/src/SignalR/perf/benchmarkapps/Crankier/Agent.cs#L212
    为什么要干掉那些喜欢卖弄细枝末节的家伙.
    为什么要干掉那些喜欢卖弄细枝末节的家伙.
    对新手来说,所以原则上需要异步等待,则 await ;不需要等待,则不需要用 await ;需要同步等待,则使用 wait()。
    3,Task.Run() 返回类型为 Task,其实和你所谓的 *Async 方法是一摸一样的,也可以遵循上面的原则。
    4,本来就是 Task 异步方法,再套 Task.Run ,没有必要

  • 資深大佬 : nannanziyu

    另外实际项目中一会要 await, 一会儿又要迅速返回,并不是设计逻辑有问题
    1,用生活中的例子来说,同样是送走来家里玩的同小区客人。如果是大人的话,送出门就可以了,无需确认,直接返回就好;而假如是孩子的小学同学,因为年龄小,所以需要等待对方家长打电话确认到家才可以,所以要 await
    2,用代码中的例子来说,同样删除缓存文件。假如你删除后,要创建同名文件,那么就需要等待;假如删除后不做其他事情,删除成功与否也不重要,那么就可以立刻返回

  • 主 資深大佬 : damingxing

    @nannanziyu
    我刚起床,你举的例子正好印证了我的看法.

    PingWorker 这里不是正好正好封装了 PingAsync 吗.
    另外我好好想了一下,你说的立即返回本身也不对.
    如果 DoAsync 里面有一个 await Do2Async(),事实上就卡住 Do2Async 这里异步了.

    对于普通开发人员来讲,不了解内部代码情况下,直接调用 DoAsync 就是不合规范的,所以必须先封装.
    首先不一定能达到想要的目的(立即返回),其次这样迫使检查人员还需要检查内部代码,增加维护难度.

    一句话,符合规范才是最重要的. 对于极端情况,就封装使其符合规范.

  • 資深大佬 : nannanziyu

    卡住异步,你真的知道你在说什么吗?

  • 資深大佬 : nannanziyu

    我不是想争辩什么,只是难得看到一个写 c#的,想点拨下。算了,你赢了

  • 主 資深大佬 : damingxing

    我说的方法,是用 Task.Run 把一个异步等待的函数放入后台执行,是为了确保达到你说的“立即返回”的效果.
    虽然都是返回 Task,但是执行的方法是完全可能不同的,怎么能说一摸一样呢. 为了符合场景当然有必要.

  • 主 資深大佬 : damingxing

    @nannanziyu 不是谁赢的问题,你的思维模式和炫技真的没两样. 现在你纠结卡住的意思,我也是服了.

    DoA()
    SendLogAsync()
    DoB()

    如果 SendLogAsync()内是
    Task SendLogAsync()
    {
    …
    await DoSomethingAsync();
    …
    }

    DoB()并不会因为 SendLogAsync()调用而立即执行

  • 主 資深大佬 : damingxing

    @nannanziyu 我很喜欢 C#

  • 資深大佬 : nannanziyu

    @damingxing
    明确告诉你, 这个例子里 DoB() 会立即执行
    https://dotnetfiddle.net/Y0xiiI

  • 主 資深大佬 : damingxing

    @nannanziyu
    好吧,你已经成功的讲一个规范问题转换成一个炫技问题.

    关于执行的流程我确实没有清楚. 但是这个不是问题的关键所在,因为按照规范我也不会这么去写,也就不会跟你纠结 DoB 是否会立即执行这种问题,很简单,对我来说异步方法就是异步调用,如果要把异步方法转为同步调用必须谨慎封装. 我也没看出我的封装有任何问题和难以理解的地方.

    而从另一方面讲,你那种调用方法有非常不安全的地方. 你无法保证能捕获到 SendLogAsync()内的异常,甚至无法保证它能够完整执行. 当然这个问题在我的封装内也存在,所以谨慎封装是必须的.

    所以综合考虑,我并不认为向你所说的直接调用一个异步方法是正确的. 当够避免的情况下更应该避免. 在我司的项目中更完全没有必要直接调用,这就是炫技狂真正的问题所在.

  • 主 資深大佬 : damingxing

    @nannanziyu 我刚才又想到了,你成功的将异步问题转换为了 Task 问题,让我差点又掉入坑里

    异步包括 task,也包括 IAsyncOperation 方法。我说的意思就是说返回 IAsyncOperation 的更不能直接调用.
    IAsyncOperation 方法是否会阻塞 DoB 我还没有验证,但是你说的 3 这点就错了.

  • 資深大佬 : nannanziyu

    @damingxing
    1,你 21 的例子,说明你对 c# 异步模型的调用循序,重入,控制流完全一点概念都没有
    这不是封装不封装的问题,你对于调用时机都不明白,写出来的代码出问题的机率非常大

    2, task 就是 IAsyncAction , task<T> 就是 IAsyncOperation 。只是叫法不同,习惯叫前者。
    另外还有 c#7.0 开始新加的 GetAwaiter (也叫 ICriticalNotify? 手机打字,准确名称有点记不得了)和 IAsyncEnumerable<T> ,后面两个你可以不管,弄懂 task 和 task<T> 就能触类旁通了

    3,你别跟我争了,经历过 APM ( IAsyncResult )年代的人,平滑切入 TAP (基于任务的异步,就是你所谓的 async 和 await ),会自然明白设计原理。你没写过代码,直接写 TAP,就会知其然不知其所以然

    async Task TestAsync()
    {
    /// do something
    }
    编译完后等价于
    class TestAsync1 : IAsyncStateMachine
    {
    public AsyncTaskMethodBuilder t_builder;
    public void MoveNext()
    {
    try
    {
    /// do something
    }
    catch (Exception exception)
    {
    t_builder.SetException(exception);
    return;
    }

    t_builder.SetResult();
    }

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

    Task TestAsync()
    {
    TestAsync1 ta = new TestAsync1();
    ta.t_builder = AsyncTaskMethodBuilder.Create();
    ta.t_builder.Start(ref ta);
    return ta.t_builder.Task;
    }

    所以直接调用 TestAsync() ,并不会所谓卡住。
    你可以自己想一想加 await 之后的状态机,这个也是学习的必经之路。

  • 主 資深大佬 : damingxing

    @nannanziyu 你在规范和技术上大部分都错了. 在没有遇到一个实质性的 task 前,直接调用就是相当于同步执行. 不用杠了.

  • 資深大佬 : nannanziyu

    上面的代码是我从 9 年前的学习笔记 blog 里 copy 的,手机 copy/paste,格式比较乱,将就看吧

  • 主 資深大佬 : damingxing

    @nannanziyu 不好意思,我并不认为我按照规范作业会出现什么问题. 倒是你这样的炫技狂人出问题的概率大得多. 刚才说的异步方法同步调用的异常捕获,你就没有考虑到.

    另外我根本不需要跟你纠结内部机制,内部机制下还有内部机制,你觉得你能全部搞清楚?不遵守规范就是挖坑,只能越挖越多. 正如我刚才所说,即使我不清楚内部细节,我按照规范写也不会出问题. 但是一个自以为懂的人,却很容易陷入自己挖的坑里无法自拔.

    你现在论证的模式,就是越挖越深. 扯出来的技术越来越多,本质上就是炫技,还增加错误的风险.

  • 資深大佬 : nannanziyu

    @damingxing
    你觉得我错就我错吧,没关系,都是学习的必经之路
    你空闲的时候,把 async/await 状态机找资料学习一下,就明白了,其实并不是个复杂的问题。
    正常学习 c#,大概一年半左右能够弄明白这个概念,然后三年左右自己实现一下无栈协程,以后每个语言里的异步问题就差不多都能理解了。
    你可以收藏下这个帖子,一年以后你再回来看看

  • 資深大佬 : nannanziyu

    @damingxing
    没有这样的规范!没有这样的规范!没有这样的规范!
    重要的事情再说最后三遍吧,真的好累呀

  • 主 資深大佬 : damingxing

    @nannanziyu 我就问你”异步代码不使用同步方法调用“能出问题吗. “异步方法在非要同步调用的场景做谨慎封装”有问题吗,你就说说按照这个规范做哪里会导致问题了.

  • 主 資深大佬 : damingxing

    我现在找不到哪里写了这句话,但是我能很轻易的找到绝大多数建议就是不要用同步的代码调用异步方法,这种建议就是规范,和变量命名我觉得没什么区别.

  • 資深大佬 : nannanziyu

    @damingxing
    好吧,我最后一次解答你的问题吧
    1,我就问你”异步代码不使用同步方法调用“能出问题吗?
    这是个复杂的问题,但也是需求问题,说多了你又觉得别人炫技,就说个简单点的新手能理解的点吧
    假设 DoAsync() 要执行 1 小时
    下面代码:
    var mem = new Byte[1024*1024*1024]; //申请 1g 内存
    await DoAsync();
    那么 mem 要 1 小时后才会释放

    如果不用 await
    var mem = new Byte[1024*1024*1024]; //申请 1g 内存
    DoAsync();
    在下次 GC 时,mem 就会被释放

    2,异常捕获,通常来说会写一个 extention method 来做

    public static class Tool
    {
    public static void IgnoreException(this Task t)
    {
    t.ContinueWith(c => { var ignore = c.Exception; });
    }
    }

    DoA()
    SendLogAsync().IgnoreException();
    DoB()
    这样就可以忽略异常,不要问为什么

  • 資深大佬 : nannanziyu

    @damingxing
    quote: 你在规范和技术上大部分都错了. 在没有遇到一个实质性的 task 前,直接调用就是相当于同步执行. 不用杠了.

    我终于看明白你的意思了……
    public static async Task SendLogAsync()
    {
    // 这一行属于 在没有遇到一个实质性的 task 前
    Console.WriteLine(“SendLogAsync {0}”, DateTime.Now.ToString(“ss.fff”));
    // await Task.Delay(300);
    }

    SendLogAsync()
    DoA()

    所以你以为不加 await, 就是相当于同步执行,先执行 SendLogAsync 里的没有遇到一个实质性的 task 前的方法, 再执行 DoA()

    await SendLogAsync()
    DoA()
    所以你以为加了 await,就是异步执行,先执行 DoA(),再执行 SendLogAsync 里的没有遇到一个实质性的 task 前的方法

    ============以上是你的错误理解===============

    不是的,看下面的例子
    https://dotnetfiddle.net/9jS6s4
    无论加不加 await,都是相当于直接在 26 的代码执行第一个 movenext

  • 資深大佬 : optional

    await AsycMethod() 表示这是一个调用。
    AsycMethod() 仅仅表示 notification,当前调用方不关心结果,甚至出错了也不关心。

  • 資深大佬 : dawn009

    @nannanziyu #12 从他的行文风格看出他并不是一个虚心的人,何必教他。

  • 資深大佬 : nannanziyu

    @dawn009 难得在 iV2ex 见到一个同行,他乡遇故知的感觉,所以想和他多说几句

  • 主 資深大佬 : damingxing

    @nannanziyu 你举的例子根本不是”异步代码不使用同步方法调用“的问题,而是这里设计就不合理. 而且就算不合理,封装一下用 DoSync()替代 DoAsync()也是可以的. 就算这样,能避免的情况下也必须避免这么做.

    还有异常捕获,我的意思是 SendLogAsync()这样调用本身就是高风险的, 我提出这个问题后你才给出解决方案. 如果我不提出这个问题这里面就相当于挖了一个坑. 而且还没有保证 SendLogAsync()能够顺利执行完毕. 还得继续挖. 这就是炫技带来的一系列后果. 遵循业界常规这问题根本就不会出现.

    另外再举个例子吧. 如果 SendLogAsync()内部是这样实现的
    public static async Task SendLogAsync()
    {
    Int64 num = 100000000;
    Int64 i, j=0;
    for (i = 2; i < num; i++)
    {
    if (num % i == 0)
    {
    j = i;
    }

    }

    await Task.Delay(1000);

    }

    这样
    DoA()
    SendLogAsync()
    DoB()
    根本达不到想要的效果
    是不是 SendLogAsync()内部不碰到 await 就不立刻退出了. 是不是必须检查内部代码实现>

    相反用封装

    public static void SendLog()
    {
    Task.Run(async ()=>{ await SendLogAsync();});
    }

    再调用
    DoA()
    SendLog()
    DoB()

    则含义清晰,而且到 SendLog()后就立刻返回,完全达到想要的效果而且不违反规范,还无需知晓内部的实现

    遵守规范编程,概念清晰,无需挖坑,无需纠结内部细节.
    不遵守规范编程,概念混淆,常常容易挖坑,还要纠结内部实现.

    孰优孰劣,一测便知.

  • 資深大佬 : northpolepuppy

    @nannanziyu 大佬我也是写 C#的可是我对于多线程一无所知

  • 資深大佬 : northpolepuppy

    @nannanziyu 能否指导下怎么学习,实在是没有头绪,书也看了视频也看了学了很久但是看不懂

  • 資深大佬 : nannanziyu

    你随便吧,希望你一两年后回来看看这个帖子,数数你从头到尾一共说对了几个概念

  • 資深大佬 : neilq

    难得有大神不骄不躁心平气和的指点,珍惜点,谦虚点把。换我可能直接爱咋咋了。

    async/await 不是什么需要炫技的东西,找篇文章看一看就能懂,花不了多少时间。

    语法糖不是规范,而是让 os 底层方法方便使用而已。毕竟有一大堆连基本线程调度机制都搞不懂的人。常看微软文档的人应该经常能看见这样的表述:”不建议你使用 xxxx 写法,除非你清楚知道自己在做什么”,理解”除非”前后的差距,正确认识自己的不足。

    人家没有说你”菜”, 没有说你”水”,谁都是过来人。而你却满口”杠”,”炫技”, “狂人”。自己想一想把。机灵点的小伙子,说几句漂亮话,聊聊共同爱好,私下加个微信,可能很快就从”对 C#不熟”过度到”熟练”了。技术这条路,戒骄戒躁。言尽于此,爱咋咋。

  • 主 資深大佬 : damingxing

    @dawn009 你说不虚心就不虚心吧,我认为遵守规范是真正的虚心,承认自己很多地方不清楚,所以小心翼翼的编写不违反规范的代码.

    @nannanziyu
    我真的没兴趣纠结 await 内部是怎么实现的,什么 movenext 不 movenext 真不关心. 我提出的这些其实都是根据你说的需要“立即返回”来说的,我指出这样并不一定会立即返回. 如果用 await 来说,我本来就知道 DoB()需要等待,那么 await 后面的函数内部代码没碰到 await 前和碰到 await 后是个什么情况并不重要啊!!

    我已经累了,我想我说得够清楚了.

  • 資深大佬 : gkiwi

    看了半天,我以为你们在聊 Node 。。

  • 資深大佬 : wisunny

    @damingxing 不知你考虑过一个情况没有,当写 log 被封装成一个库了之后(大项目中很常见),为了迎合你的写法,要跑去请求其他部门修改?

  • 主 資深大佬 : damingxing

    @neilq 你这种想法本身就很危险. 每个人都觉得”不是什么需要炫技的东西,找篇文章看一看就能懂,花不了多少时间”, 不好意思,无形当中增加的成本才是最重要的. 反过来说,遵守规范编程,本身就是一种减少成本的做法,遵循的也是 KISS 原则. 理解”除非”前后的差距,如果本身不需要理解即可解决问题,真不需要去理解.

    至于你最后一段话,我就不发表评论了.

  • 主 資深大佬 : damingxing

    @wisunny 你看看我在 39 的写法,封装即可解决问题.

  • 資深大佬 : lq007

    @nannanziyu 说的挺好的,主一直没 get 到点上哈哈

  • 資深大佬 : ppphp

    吃这碗饭的这点操作都受不了吗

  • 資深大佬 : charlie21

    编译器允许你所谓的不规范代码存在,是有一定的道理的

  • 資深大佬 : catror

    感觉主还是没有理解到 nannanziyu 在六要表达的东西

  • 主 資深大佬 : damingxing

    @charlie21
    @catror

    搞技术的人走火入魔标志:
    我偏要这么搞,你看不懂是你的问题,不是我的问题.

  • 資深大佬 : kop1989

    16 说的非常好

  • 資深大佬 : 009694

    主言语里透露着一种[我要不是个落魄的编程王子,才懒得看你们菜鸡代码]的感觉,为了不表现得过于明显,拉上“规范”做背书(然而不过是不肯接受新东西)。 不过说来人家已经被主坐实 “叛徒”,自然“叛徒”做什么都是有罪的。

  • 資深大佬 : pushback

    工作炫技是好事,面试别人时炫技才是该干掉的

  • 資深大佬 : rioshikelong121

    高强度对线

  • 資深大佬 : weiceshi

    主,你是怎么达成“一整篇帖子,自己几十个回复”,一个正确的观点都没有的

  • 資深大佬 : royzxq

    没用过 C#

    但是 async 的不一定非要 await 吧

  • 資深大佬 : charlie21

    别说 “搞技术的人 blabla ”,技术的搞法 是有不同层次的

    你要比出活儿快,那你自己攒一套最佳实践是出活儿快
    你要比容错率,你要看很多很多代码才可以,而且 心平气和地看也不被搅乱,因为头脑里有更深的东西,在那个标尺之下 是有东西

    你真正有容错率之后才能指导别人,半碗水晃荡一下子就露馅了阿。在那个标尺之下,你没东西。所以在这里,你没有容错率

    今天没有人跟你杠,总有一天有人跟你杠的阿 ( 只要你踏入那个层次 ),如果就这么轻易地被杠翻了,那么 … 要么 如果你不肯开拓 (为自己开拓新标尺 新层次,给自己出出题) 的话 你就得承认你混错圈子了:把踏入的脚 要收回来

    注意:求仁得仁,我没说哪个高 哪个低,哪个标尺好 哪个标尺不好。你求仁得仁。但确实是不同的标尺。

  • 主 資深大佬 : damingxing

    @009694 我对自己编程有信心,不是建立在自己知道多少细节上的,仅仅是知道自己哪些可以做哪些不可以做而已. 按照规范编程可以在少一些所谓的知识情况下最大化收益,最小化损失,何乐不为?

  • 資深大佬 : weiceshi

    @damingxing
    你根本没理解 nannanziyu 的话,或者说你根本嘛玩意也不会
    还贴 39 的例子
    你举得那个方法根本就是错的,异步 Async 方法不能在异步方法前做耗时操作,只可以简单声明赋值等。
    如果要考虑 Async 方法会不会像你这样的菜鸟写错,那 await 根本没意义了
    所有的 Async 方法都不能 await 调用了
    因为加不加 await,效果是一样的

  • 主 資深大佬 : damingxing

    @weiceshi 怎么没理解了,那么几句话还不好理解?你说的“异步 Async 方法不能在异步方法前做耗时操作”倒是有点参考意义. 算了,不跟你们争了,我改过来.

  • 主 資深大佬 : damingxing

    @weiceshi “异步 Async 方法不能在异步方法前做耗时操作” 这几句话有几分道理.
    但是你怎么保证人家就不这么写了?我加一个 Task.Run()不更安全吗?

  • 資深大佬 : weiceshi

    我晕,本来以为是技术讨论
    通篇看完,发现主所有发言总结下来就是一句,“我新手,我啥也不懂,我连方法哪个先执行哪个后执行也不知道,你别管我,我就要这样写”
    你这不叫杠,你这叫天桥下面卖丑
    你这一整篇下来,连方法哪个先执行哪个后执行都不知道,你写出来的代码能 run 吗?

  • 主 資深大佬 : damingxing

    @weiceshi 再说了
    如果按照规范写,Async()里面即使有你说的耗时操作,哪里会影响到程序执行问题呢?你这个提法算规范吗

  • 資深大佬 : shintendo

    我不知道的都是不重要的细枝末节.jpg

  • 資深大佬 : nannanziyu

    @damingxing
    但是你怎么保证人家就不这么写了?我加一个 Task.Run()不更安全吗?

    是啊,所以的 Async 方法都不能保证,所以 await 还有啥意义?
    所有的 await 方法都要考虑会不会有菜鸡在写耗时同步执行,那所有的方法都用 Task.run 开个线程池执行吧
    你这不是傻的嘛

  • 主 資深大佬 : damingxing

    @weiceshi 你这就属于瞎说了,你就说说我哪里不知道谁先随后了?怎么就不能 run 了?你这样胡扯更可怕. 更何况那种需求也不是我提出来的,理论上根本就不会发生在我这里。就按照我在 39 的写法,你觉得会引起什么问题了?

  • 資深大佬 : nannanziyu

    我受不了了,拉黑了,你是对的,我错了

  • 資深大佬 : NicholasYX

    抛开主的问题 单谈炫技
    我看到这种我会觉着 卧槽还能这么写?然后去查一通 而不是觉着这人装逼明明可以那么写他却这么写故意让我看不懂浪费我时间

  • 主 資深大佬 : damingxing

    @nannanziyu 这一点确实是我考虑不周,但是即使是这样我按照规范写也不会有问题呀. 耗时的计算自然会丢到线程里去计算,和你这个又不是一个场景了吧.

    我就问一句,在 await DoAsync()没有任何问题的情况下,你会不会用 DoAsync()?这样乱用是不是脑子进水了,你直接回答这个问题就结了.

  • 主 資深大佬 : damingxing

    @nannanziyu 拉黑就拉黑,我对炫技狂无可奈何.

  • 主 資深大佬 : damingxing

    @NicholasYX 是啊,这只是炫技狂的一个极小的细节而已.
    你还没看到炫技狂丢下一堆通用的东西不用,非要自己造轮子的类呢.
    放着好端端的轮子不用偏要看他的,纯属浪费时间.

  • 資深大佬 : Alexhohom

    主一年后再来看,不知道作何感想

  • 資深大佬 : weiceshi

    @damingxing

    如果 DoAsync() 结果无意义,那么当然不用 await 啊
    因为用了 await,后续操作会无意义的延时啊
    你真的连这个都不明白吗?

  • 資深大佬 : weiceshi

    当然你也可以不直接调 DoAsync()
    而是用 Task.Run 无意义的包一层
    当然,你也可以无意义的包十层
    Task.Run(async () =>
    await Task.Run(async () =>
    {
    await Task.Run(async () =>
    {
    await Task.Run(async () =>
    {
    await Task.Run(async () =>
    {
    await Task.Run(async () =>
    {
    await Task.Run(async () =>
    {
    await Task.Run(async () => { await DoAsync();});
    });
    });
    });
    });
    });
    }));

    但是推荐直接调……

  • 資深大佬 : weiceshi

    @nannanziyu 那么不骄不躁心平气和,衬得我好像多暴躁……
    好吧,那我也好好跟你解释下

    1,如果返回结果和执行状态无意义,那么直接调就可以了
    await DoA();
    SendLogAsync(“A”);
    SendLogAsync(“B”);
    SendLogAsync(“C”);
    SendLogAsync(“D”);
    SendLogAsync(“E”);
    SendLogAsync(“F”);
    SendLogAsync(“G”);
    await DoB();

    因为假如都加 await,真正需要的 DoB 会被无意义的延迟很多秒
    2,假如这些 SendLogAsync 本身是有序的,也就是执行完第一个,才能执行第二个,以此类推。但是整个 SendLog 的返回结果和执行状态无意义,那么才需要用 Task.Run 来包
    await DoA();
    Task.Run(async () =
    {
    await SendLogAsync(“A”);
    await SendLogAsync(“B”);
    await SendLogAsync(“C”);
    await SendLogAsync(“D”);
    await SendLogAsync(“E”);
    await SendLogAsync(“F”);
    await SendLogAsync(“G”);
    }

    await DoB();

  • 資深大佬 : weiceshi

    另外 #71 的 @NicholasYX 似乎实在讽刺主,而不是你在 #74 里以为的帮你说话……

  • 主 資深大佬 : damingxing

    @weiceshi 谢你了,我看到你一堆没有 await 的 Async()方法已经头大了.
    道理容易懂,说了这个就是个规范问题,不需要再解释了.

  • 資深大佬 : weiceshi

    @damingxing 人是社会性和思想性的动物,交流总要有意义
    里多少人跟你说了,根本没有这个规范,你怎么就…… 这么杠呢

  • 主 資深大佬 : damingxing

    @weiceshi 行,你们都对,就你们聪明. 反正我只关心我需要知道的东西.

  • 資深大佬 : neilq

    咱先不说 await 到底怎么用,我点评一下这件事,这真实一个现象级的帖子 —— 过来人指点新手反遭嘲讽,十年老技工的专业基础知识(专业基础知识这个词我应该没用错)被新手的规范按在地上摩擦,傍观者看不下去各种帮忙反击。但是最初的两个人仍是那么纯粹。

    哪怕是所有都认为主错了,主仍然还觉得自己观点正确,对自己丝毫没有怀疑,睥睨天下。纯粹。

    哪怕是被冠上了”炫技狂”,”走火入魔”,”脑子进水”这类明着的侮辱词汇,@nannanziyu 兄直到几十层最后两句还在试图纠正主,这是另一份纯粹,值得敬佩。这位兄弟的昵称也值得品味,nannanziyu, 喃喃自语。

    再说其他旁观者,什么鲁迅体嘲讽,什么求仁得仁,什么天桥下面的卖丑,word 天,整出一堆文学家,你们说话怎么那么好听,真得发出去让别人看看,这是行外人对程序员的刻板印象的一次强硬反击。

    我要特别说说这位兄弟 @weiceshi,你天生带着一股幽默,”主,你是怎么达成“一整篇帖子,自己几十个回复”,一个正确的观点都没有的”, 看到你这句话我就已经快忍不住了,又看到你后面的包十层包大人我的小口口里面的水水直接就喷出来,把我的衣物都高湿了。

    哪怕是被冠上了”炫技狂”,”走火入魔”,”脑子进水”这类明着的侮辱词汇,@nannanziyu 兄直到几十层最后两句还在试图纠正主,这是另一份纯粹,值得敬佩。这位兄弟的昵称也值得品味,nannanziyu, 喃喃自语。

    再说其他旁观者,什么鲁迅体嘲讽,什么求仁得仁,什么天桥下面的卖丑,word 天,整出一堆文学家,你们说话怎么那么好听,真得发出去让别人看看,这是行外人对程序员的刻板印象的一次强硬反击。

    我要特别说说这位兄弟 @weiceshi,你天生带着一股幽默,”主,你是怎么达成“一整篇帖子,自己几十个回复”,一个正确的观点都没有的”, 看到你这句话我就已经快忍不住了,又看到你后面的包十层包大人我的小口口里面的水水直接就喷出来,把我的衣物都高湿了。一句天桥下面卖丑,眼瞅着你就要暴躁起来了,可能是被 @nannanziyu 的行为所征服,突然画风一转,完成了个人思想道德的升华。有意思,有意思。

  • 資深大佬 : Rwing

    感动,竟然在 V2 看到 C#的技术讨论

  • 資深大佬 : atwoodSoInterest

    君子疾夫舍曰欲之而必为之辞

  • 主 資深大佬 : damingxing

    @weiceshi 你在 78 的写法,只有 2 我才是赞同的. 符合规范.

    我举出一个更好的例子可以说明为什么要按照规范来写.

    因为你无法知晓 SendLogAsync 本身是不是线程安全的(尽管在这个场景下大概率是,但是如果是别的场景呢,这点我想不用解释了吧),所以在没有审查源码的情况下,使用你的方法 2 才是 ok 的,跟是否需要得到返回结果没有关系.

  • 主 資深大佬 : damingxing

    这一点也可以运用到 39 ,SendLog()封装 SendLogAsync ()时候要考虑线程安全问题.

  • 主 資深大佬 : damingxing

    @nannanziyu 如果 SendLogAsync() 不是线程安全的,你如何敢不用 await 直接调用 SendLogAsync()?

    这个坑还是我目前想到的,说不定还有更多坑.

  • 資深大佬 : jeansfish

    你通篇所谓的规范是什么呢?

  • 資深大佬 : weiceshi

    @damingxing
    又通过百度发现了一个华点啊,盲生,都扯到线程安全上来了
    thread-safe 和你加不加 await 有一毛钱关系吗?
    你全宇宙都加上 await,然后两个线程同时调,你就不用考虑线程同步了?
    你分得清异步模型和业务逻辑的区别不?

  • 主 資深大佬 : damingxing

    @weiceshi 百度你个毛线,我搜索从来都是 google. SendLogAsync 内怎么就不可以有线程了?用 await 我可以等待执行完毕,不用你能行?

  • 主 資深大佬 : damingxing

    @weiceshi 再一个,刚才这个问题根本不是我搜索想到的,只是无意间想到而已,你不要臆想行不?

  • 資深大佬 : shintendo

    “百度你个毛线,我搜索从来都是 google”看到这里实在忍不住笑了

  • 資深大佬 : weiceshi

    @damingxing 你这理解能力太差了…… 怪不得别人讽刺你的话,你都听不懂
    Task WindowSizeChange()
    {
    DoA()
    await SendLogAsync()
    DoB()
    }

    这个用了 await 了,然后 window 大小连续更改了两次,调用了两次 Func(),你一样要考虑线程同步的问题,你不明白这个吗?不能用 await 来解决线程同步的问题啊

    解决线程同步对你来说太深了,你可以了解下 SemaphoreSlim……
    哥呀,你真的……

  • 資深大佬 : xgfan

    lz,建议转 java7 。很适合你。

  • 資深大佬 : weiceshi

    边滑水边等待你的下一个华点……

  • 資深大佬 : kop1989

    针对语法糖能战 100 ,加油啊。
    @weiceshi #96 顶住

  • 資深大佬 : weiceshi

    话说整篇过下来,主为了杠,通过不断百度,哦不,google,还是进步了不少,至少还是知道了几个名词。
    刚开始的几,真的是……居然以为加 await 就是异步调用,不加就是同步调用,我估计 nannanziyu 兄当时都惊呆了吧……

    不过没事,有进步就好,毕竟有先贤说过“想要获得一个对的答案,那么最好的方法就是先给出一个错误的来”

    主通过先贤的方法,while(true) {await 卖丑; await 获取知识; await google 下一个华点;} 的过程值得我们借鉴;不过要是天桥献艺的同时,能给个打赏二维码就好了,知识铜币两不误嘛,对不对

  • 主 資深大佬 : damingxing

    @weiceshi 我对杠这个玩意一点兴趣都没有. 我只是觉得你们弄错了.

    这是我设计的 SendLogAsync() ,我还没设计成线程不安全,只是为了说明可以创建线程在里面

    private async Task<Int64> SendLogAsync()
    {
    Int64 j = 0;
    await Task.Run(() =>
    {
    Int64 num = 600000000;
    Int64 i = 0;
    for (i = 2; i < num; i++)
    {
    if (num % i == 0)
    {
    j = i;
    }

    }

    });

    Debug.WriteLine(“{0} SendLogAsync”, j);
    return j;
    }

    另外,

    public void DoA()
    {
    Debug.WriteLine(“{0} DoA”, DateTime.Now.ToString(“ss.fff”));
    }

    public void DoB()
    {
    Debug.WriteLine(“{0} DoB”, DateTime.Now.ToString(“ss.fff”));
    }

    调用
    for (var k = 0;k<3;k++)
    {
    DoA();
    await SendLogAsync();
    DoB();
    }
    结果
    18.225:{0} DoA
    300000000 SendLogAsync
    22.357:{0} DoB
    22.358:{0} DoA
    300000000 SendLogAsync
    26.468:{0} DoB
    26.469:{0} DoA
    300000000 SendLogAsync
    30.612:{0} DoB
    改成
    for (var k = 0;k<3;k++)
    {
    DoA();
    SendLogAsync();
    DoB();
    }
    结果
    08.930:{0} DoA
    08.942:{0} DoB
    08.943:{0} DoA
    08.986:{0} DoB
    08.988:{0} DoA
    09.014:{0} DoB
    300000000 SendLogAsync
    300000000 SendLogAsync
    300000000 SendLogAsync

    这说明的问题应该很清楚了吧. 你举的例子在这里不会发生线程冲突好不.
    但是如果直接下面一种调用,如果有共享变量明显会有线程冲突的可能.

  • 資深大佬 : weiceshi

    @damingxing 请仔细阅读 94

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具