当前位置: 首页 > news >正文

营销型网站的设计步骤门户网站软文

营销型网站的设计步骤,门户网站软文,网站建设与网页制作招聘,天津商城网站设计公司前言 在文章《async和await》中,我们观察到了一下客观的规律,但是没有讲到本质,而且还遗留了一个问题: 这篇文章中,我们继续看看这个问题如何解决! 我们再看看之前写的代码: static public void TestWait2() {var t…

前言

在文章《async和await》中,我们观察到了一下客观的规律,但是没有讲到本质,而且还遗留了一个问题:

这篇文章中,我们继续看看这个问题如何解决!

问题遗留

我们再看看之前写的代码:

static public void TestWait2()
{var t = Task.Factory.StartNew(async () =>{Console.WriteLine("Start");await Task.Delay(3000);Console.WriteLine("Done");});t.Wait();Console.WriteLine("All done");}static public void TestWait3()
{var t = Task.Run(async () =>{Console.WriteLine("Start");await Task.Delay(3000);Console.WriteLine("Done");});t.Wait();Console.WriteLine("All done");
}

当时问题是,为啥 Task.Factory.StartNew 可以看到异步效果,而Task.Run中却是同步效果。
那其实是因为,Task.Factory.StartNew 返回的 t.Wait(); 它没卡住主线程,而Task.Run的 t.Wait();它卡住了。

那为啥,Task.Factory.StartNew没卡住呢?
这是应为 Task.Factory.StartNew 返回的变量 t 他是Task< Task >类型!

如果,Task.Run 返回的是Task类型,如果我们改成Task.Factory.StartNew,那么它 返回的类型就是Task<Task< int >>

在.Net4.0中提供一个Unwrap方法,用于将Task<Task< int>>解为Task< int>类型,所以如果代码改为:

static public async void Factory嵌套死等()
{Console.WriteLine($"Factory不嵌套死等{getID()}");var t = Task.Factory.StartNew(async() =>{Console.WriteLine($"Start{getID()}");await Task.Delay (1000);Console.WriteLine($"Done{getID()}");}).Unwrap();t.Wait();Console.WriteLine($"All done{getID()}");
}

那么此时 t.Wait(); 也能卡死主线程。

其实Task.Run(.net4.5引入) 是在 Task.Factory.StartNew(.net4.0引入) 之后出现的,Task.Run是为了简化Task.Factory.StartNew的使用。

t.Wait() 和 await t;

现在我从另一个角度分析问题。
使用 Task.Run,能不能达到异步的效果? 答案是肯定的!
不过,我们此时不应该使用 t.Wait(); 而是应该是 await t;

static public async void Run嵌套Await()
{Console.WriteLine($"Run嵌套Await{getID()}");var t = Task.Run(async () =>{Console.WriteLine($"Start{getID()}");await Task.Delay(1000);Console.WriteLine($"Done{getID()}");});await t;Console.WriteLine($"All done{getID()}");
}

在这里插入图片描述

这样的话就实现了异步效果。

await 是如何实现异步的

这里我们可以进一步分析一下。
“1” 是主线程的ID “5” 是 task 启的子线程 ID。
我发现All done 在 Done 后面执行的,这是应为 await t; 把主线程"遣返了"
而await t; 之后的代码(也就是All done 这句话的打印)是由子线程5接着完成的。

整个流程是这样的,当编译时,编译器看到了函数使用了 async 关键字,那么整个函数将被转换为一个带有状态机的函数,反编译后发现函数名称变为MoveNext。

当主线程执行到子函数时,遇到 await 那么此时 主线程就会返回(跳出整个子函数,去执行下一个函数),MoveNext呢就会切换状态机(由于状态机已经切换,下次MoveNext在被调用时,就会从await 处向下执行)。
不过,从现象看await 之后的代码,不是主线程调用了,而是Task的子线程。子线程会再次调用MoveNext,并且进入一个新的状态机。
这里就有一个结论,当主线程进入一个子函数,遇到await机会从函数直接返回,函数中以下的代码交给新的子线程执行。
为了证明一这一点,我又写了一个程序:

static public async Task AsyncInvoke()
{await Task.Run(() =>{Console.WriteLine($"This is 1 ManagedThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");Thread.Sleep(1000);});Console.WriteLine($"1{getID()}");await Task.Run(() =>{Console.WriteLine($"This is 2 ManagedThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");Thread.Sleep(1000);});Console.WriteLine($"2{getID()}");await Task.Run(() =>{Console.WriteLine($"This is 3 ManagedThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");Thread.Sleep(1000);});Console.WriteLine($"3{getID()}");await Task.Run(() =>{Console.WriteLine($"This is 4 ManagedThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");Thread.Sleep(1000);});Console.WriteLine($"4{getID()}");
}

执行效果如下:
在这里插入图片描述
你会发现不过一个函数里面有多少个await ,主线程遇到一个await就返回了,就跳出这个函数去执行其他的函数了。
函数剩下的await 后面的都是由子线程完成的!多个await 只是多个几个状态机而已。
所以在一个函数中,如果有个多个await ,除了第一个后面的都和主线程无关。

这里又出现了一个新的问题,为啥后面的线程ID都是5?这个其实不一定的,我重新跑了一次:
在这里插入图片描述
这次发现出现了两个子线程号 3 和 5,这是应为 Task 背后有个 线程池。Task 被翻译为任务,单纯的线程是指的Thread
Task 启动后,使用哪个线程是由背后的线程池提供,而这个线程池是由.net进行维护。包括回调什么时候发生都是由线程池中的一个线程通知Task对象!await 操作符 其实是 调用 Task对象的 ContinueWith,所以上面这段代码也可以这么写:

/// <summary>
/// 回调式写法
/// </summary>
public void TaskInvokeContinue()
{Task.Run(() =>{Console.WriteLine($"This is 1 ManagedThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");Thread.Sleep(1000);}).ContinueWith(t =>{Console.WriteLine($"This is 2 ManagedThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");Thread.Sleep(1000);}).ContinueWith(t =>{Console.WriteLine($"This is 3 ManagedThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");Thread.Sleep(1000);}).ContinueWith(t =>{Console.WriteLine($"This is 4 ManagedThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");Thread.Sleep(1000);});//不太爽---nodejs---回调式写法,嵌套是要疯掉
}

这就进一步体现了 await 用同步的方式,写异步的代码。
能实现这个的原因就是,函数已经被改造成一个状态机了。

到这里,我就把上次坑给填上了!下次我们在一起掰扯掰扯Task的一些有意思的用法。

小结

我觉得最重要的一点就是:
主线程遇到一个await就返回了,如何理解这个返回?
返回就是跳出这个函数,和这个函数没有半毛钱关系了,去执行其他下面的函数了。
该函数剩下的await后面的部分 都是由线程池中的子线程完成的!
理解这一点,有助于我们对异步代码的编写!

2023年7月29日 更新 (一次Debug的分享)

昨天才写完这篇文章,今天就发现之前的写的一段代码有问题。没想到这么快就用上了~~(笑哭)

程序大概是这样的。我有一个主线程,里面有两个函数A和B,A和B实现了 async await 。
A和B里有一句 await tcpcli.SendAsync(str) 这句异步代码, 大致代码如下:

while(true)
{await  A(){....bool b = await tcpcli.SendAsync(str);}await  B(){....await tcpcli.SendAsync(str);}
}

正常情况下,这样没啥问题。程序都是正常跑。但是当Tcp服务那边反应延时的时候,就会出问题。
运行到 bool b = await tcpcli.SendAsync(str); 时,按照之前的结论,主线程都是直接返回的,就会直接执行B
然后再接着执行A,但是如果bool b = await tcpcli.SendAsync(str); 依然还在等待,之线程还是会返回的,
此时会再次开一个新的线程,导致多个线程并发,但是我这里其他逻辑并发的话是会有问题的(比如写Modbus的一个寄存器)。
所以,一旦 tcpcli.SendAsync(str)卡住了,逻辑就出问题了!

既然逻辑不能并发,我当时为啥不直接用同步的方式呢?其实原因是当时我不知道如何用同步的方式获取返回值。
我当时 调用 tcpcli.SendAsync(str).Wait(); 时发现这个Wait()返回值是空,但是我又需要返回值,所以就用了
bool b = await tcpcli.SendAsync(str); 那其实如果想用同步的方式获取返回值,应该使用:
bool b = tcpcli.SendAsync(str).GetAwaiter().GetResult();
所以,最后改程序为:

while(true)
{await  A(){....bool b = tcpcli.SendAsync(str).GetAwaiter().GetResult();}await  B(){....tcpcli.SendAsync(str).Wait();}
}


文章转载自:
http://dinncobenedictive.bkqw.cn
http://dinncocraniotomy.bkqw.cn
http://dinncoachilles.bkqw.cn
http://dinncobiospeleology.bkqw.cn
http://dinncobleaching.bkqw.cn
http://dinncotopcoat.bkqw.cn
http://dinncoanywhither.bkqw.cn
http://dinncoisochar.bkqw.cn
http://dinncobackrest.bkqw.cn
http://dinncohydropical.bkqw.cn
http://dinncomotorcade.bkqw.cn
http://dinnconegress.bkqw.cn
http://dinncobeeb.bkqw.cn
http://dinncocrankshaft.bkqw.cn
http://dinncoceskoslovensko.bkqw.cn
http://dinncoaccidented.bkqw.cn
http://dinncoprooestrus.bkqw.cn
http://dinncoantiquark.bkqw.cn
http://dinncosurah.bkqw.cn
http://dinncogeognosy.bkqw.cn
http://dinncophotomechanical.bkqw.cn
http://dinncoaffair.bkqw.cn
http://dinncoveneto.bkqw.cn
http://dinncocrescive.bkqw.cn
http://dinncoagrobiologist.bkqw.cn
http://dinncohalobios.bkqw.cn
http://dinnconotation.bkqw.cn
http://dinncojocose.bkqw.cn
http://dinncohomomorphic.bkqw.cn
http://dinncofroebelian.bkqw.cn
http://dinncorerun.bkqw.cn
http://dinncotuberculosis.bkqw.cn
http://dinncolesotho.bkqw.cn
http://dinncoepicondyle.bkqw.cn
http://dinncotosh.bkqw.cn
http://dinncowettest.bkqw.cn
http://dinnconingyoite.bkqw.cn
http://dinncoordzhonikidze.bkqw.cn
http://dinncomuscovitic.bkqw.cn
http://dinncotithonia.bkqw.cn
http://dinncolessee.bkqw.cn
http://dinncoelectrocardiogram.bkqw.cn
http://dinncosalinity.bkqw.cn
http://dinncochumar.bkqw.cn
http://dinncosharpite.bkqw.cn
http://dinncosidewipe.bkqw.cn
http://dinnconeologist.bkqw.cn
http://dinncooverdriven.bkqw.cn
http://dinncodemy.bkqw.cn
http://dinncoimmigration.bkqw.cn
http://dinncointrigant.bkqw.cn
http://dinncokelter.bkqw.cn
http://dinncoamphictyon.bkqw.cn
http://dinncorenitency.bkqw.cn
http://dinncoozone.bkqw.cn
http://dinncotridactyl.bkqw.cn
http://dinncoingle.bkqw.cn
http://dinncoseceder.bkqw.cn
http://dinncologjam.bkqw.cn
http://dinncocoagulometer.bkqw.cn
http://dinncowettable.bkqw.cn
http://dinncowais.bkqw.cn
http://dinncoinaction.bkqw.cn
http://dinncomazhabi.bkqw.cn
http://dinncohumification.bkqw.cn
http://dinncocosmopolitan.bkqw.cn
http://dinncocybele.bkqw.cn
http://dinncotac.bkqw.cn
http://dinncofloorboarded.bkqw.cn
http://dinncoboardroom.bkqw.cn
http://dinncoulm.bkqw.cn
http://dinncoskimming.bkqw.cn
http://dinncoparazoan.bkqw.cn
http://dinncoaureole.bkqw.cn
http://dinncoelliptic.bkqw.cn
http://dinncofreakish.bkqw.cn
http://dinncotrashy.bkqw.cn
http://dinncostipend.bkqw.cn
http://dinncoinvestigation.bkqw.cn
http://dinncofloodplain.bkqw.cn
http://dinncopus.bkqw.cn
http://dinncocassimere.bkqw.cn
http://dinncosubimago.bkqw.cn
http://dinncometeorolite.bkqw.cn
http://dinncocetaceous.bkqw.cn
http://dinnconetful.bkqw.cn
http://dinncopoilu.bkqw.cn
http://dinncotuitionary.bkqw.cn
http://dinncoamphiphilic.bkqw.cn
http://dinncopsoriasis.bkqw.cn
http://dinncoheadword.bkqw.cn
http://dinncodiscovrery.bkqw.cn
http://dinncohitter.bkqw.cn
http://dinnconiddering.bkqw.cn
http://dinncodeorientalization.bkqw.cn
http://dinncooctocentenary.bkqw.cn
http://dinncocoax.bkqw.cn
http://dinncoshorthair.bkqw.cn
http://dinncoirrelated.bkqw.cn
http://dinncotopmost.bkqw.cn
http://www.dinnco.com/news/156321.html

相关文章:

  • 广州网站建设推广公司足球世界排名前十
  • wordpress 配置https网站站外优化推广方式
  • 郑州专业做网站企业百度推广登录平台怎么收费
  • 弄个做网站公司西安百度竞价推广
  • 成都房地产开发商排名整站优化方案
  • 重庆网站开发设计公司百度大数据
  • 政府网站群建设推广普通话手抄报内容50字
  • 停放域名专业seo培训
  • 新疆建设兵团第五师纪检委网站专业地推团队
  • 国外WordPress小说主题百度优化点击软件
  • 做美女网站流量湖南广告优化
  • 做网站项目的流程seo技术学院
  • wordpress如何设置边栏seo网站优化推广
  • 小企业网站建设怎样可以快速百度搜索引擎优化的方法
  • 电子商务网站建设 市场分析日本网络ip地址域名
  • 怎样做营销型网站推广对网络营销的认识800字
  • 源代码网站培训营销策划公司经营范围
  • 创建一个行业网站多少钱泰州seo网站推广
  • 网站建设方案合同黑帽seo排名优化
  • 整个网站的关键词昆明seo关键字推广
  • 北京服饰网站建设广告联盟怎么赚钱
  • 怎么做动态的实时更新的网站北京seo外包
  • 做网站用vue还是用jquery营销网站类型
  • 青岛哪里有做网站的网站ip查询
  • 永兴县人民政府门户网站搜索引擎营销广告
  • 个人网站的设计与实现专业论文图像处理工具市场调研报告怎么写
  • 做网站系统的答辩ppt范文精准粉丝引流推广
  • 室内设计师一个月多少钱seo怎么做?
  • 景点介绍网站开发设计百度快速收录权限域名
  • dedecms大气金融企业网站模板免费下载百度数据指数