HTML5技术

C#异步的世界【上】 - 农码一生(3)

字号+ 作者:H5之家 来源:H5之家 2017-01-18 13:00 我要评论( )

public void MyAction(){ string str1 = string .Empty, str2 = string .Empty, str3 = string .Empty;IAsyncResult asyncResult1 = null , asyncResult2 = null , asyncResult3 = null ;asyncResult1 = func1().Be

public void MyAction() { string str1 = string.Empty, str2 = string.Empty, str3 = string.Empty; IAsyncResult asyncResult1 = null, asyncResult2 = null, asyncResult3 = null; asyncResult1 = func1().BeginInvoke(, t => { str1 = func1().EndInvoke(t); Debug.WriteLine(+ Thread.CurrentThread.ManagedThreadId); asyncResult2 = func2().BeginInvoke(, a => { str2 = func2().EndInvoke(a); Debug.WriteLine(+ Thread.CurrentThread.ManagedThreadId); asyncResult3 = func3().BeginInvoke(, s => { str3 = func3().EndInvoke(s); Debug.WriteLine(+ Thread.CurrentThread.ManagedThreadId); }, null); }, null); }, null); asyncResult1.AsyncWaitHandle.WaitOne(); asyncResult2.AsyncWaitHandle.WaitOne(); asyncResult3.AsyncWaitHandle.WaitOne(); Debug.WriteLine(str1 + str2 + str3); } 

除了难看、难读一点好像也没什么 。不过真的是这样吗?

asyncResult2是null?
由此可见在完成第一个异步操作之前没有对
asyncResult2进行赋值,asyncResult2执行异步等待的时候报异常。那么如此我们就无法控制三个异步函数,按照一定顺序执行完成后再拿到返回值。(理论上还是有其他办法的,只是会然代码更加复杂)

 

是的,现在该我们的TAP登场了。

只需要调用Task类的静态方法Run,即可轻轻松松使用异步。

获取返回值:

var task1 = Task<string>.Run(() => { Thread.Sleep(1500); Console.WriteLine(+ Thread.CurrentThread.ManagedThreadId); ; }); //其他逻辑 task1.Wait(); var value = task1.Result;//获取返回值 Console.WriteLine(+ Thread.CurrentThread.ManagedThreadId);

现在我们处理上面多个异步按序执行:

Console.WriteLine(+ Thread.CurrentThread.ManagedThreadId); string str1 = string.Empty, str2 = string.Empty, str3 = string.Empty; var task1 = Task.Run(() => { Thread.Sleep(500); str1 = ; Console.WriteLine(+ Thread.CurrentThread.ManagedThreadId); }).ContinueWith(t => { Thread.Sleep(500); str2 = ; Console.WriteLine(+ Thread.CurrentThread.ManagedThreadId); }).ContinueWith(t => { Thread.Sleep(500); str3 = ; Console.WriteLine(+ Thread.CurrentThread.ManagedThreadId); }); Thread.Sleep(2500);//其他逻辑代码 task1.Wait(); Debug.WriteLine(str1 + str2 + str3); Console.WriteLine(+ Thread.CurrentThread.ManagedThreadId);

[效果图]

我们看到,结果都得到了,且是异步按序执行的。且代码的逻辑思路非常清晰。如果你感受还不是很大,那么你现象如果是100个异步方法需要异步按序执行呢?用APM的异步回调,那至少也得异步回调嵌套100次。那代码的复杂度可想而知。

 

延伸思考
  • WaitOne完成等待的原理

  • 异步为什么会提升性能

  • 线程的使用数量和CPU的使用率有必然的联系吗

  •  

    问题1:WaitOne完成等待的原理

    在此之前,我们先来简单的了解下多线程信号控制AutoResetEvent类。

    var _asyncWaitHandle = new AutoResetEvent(false); _asyncWaitHandle.WaitOne();

    此代码会在 WaitOne 的地方会一直等待下去。除非有另外一个线程执行 AutoResetEvent 的set方法。

    var _asyncWaitHandle = new AutoResetEvent(false); _asyncWaitHandle.Set(); _asyncWaitHandle.WaitOne();

    如此,到了 WaitOne 就可以直接执行下去。没有有任何等待。

    现在我们对APM 异步编程模型中的 WaitOne 等待是不是知道了点什么呢。我们回头来实现之前自定义异步方法的异步等待。

    public class MyWebRequest : IAsyncResult { AsyncCallback _asyncCallback; private AutoResetEvent _asyncWaitHandle; public MyWebRequest(AsyncCallback asyncCallback, object state) { _asyncCallback = asyncCallback; } SetComplete(string result) { Result = result; IsCompleted = true; _asyncWaitHandle.Set(); if (_asyncCallback != null) { _asyncCallback(this); } } Result { get; set; } AsyncState { get { throw new NotImplementedException(); } } WaitHandle AsyncWaitHandle { } CompletedSynchronously { get { throw new NotImplementedException(); } } IsCompleted { get; private set; } }

    红色代码就是新增的异步等待。

    【执行步骤】

     

    问题2:异步为什么会提升性能

    比如同步代码:

    Thread.Sleep(10000);//假设这是个访问数据库的方法 Thread.Sleep(10000);//假设这是个访问FQ网站的方法

    这个代码需要20秒。

    如果是异步:

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • 那些年搞不懂的术语、概念:协变、逆变、不变体 - 农码一生

      那些年搞不懂的术语、概念:协变、逆变、不变体 - 农码一生

      2016-08-30 17:00

    • 用canvas画简单的“我的世界”人物头像 - 玉菲莎

      用canvas画简单的“我的世界”人物头像 - 玉菲莎

      2016-07-27 14:00

    • JS运动从入门到兴奋1 - 沫晴的前端世界

      JS运动从入门到兴奋1 - 沫晴的前端世界

      2016-07-16 11:00

    • 过目不忘JS正则表达式 - 沫晴的前端世界

      过目不忘JS正则表达式 - 沫晴的前端世界

      2016-07-14 14:00

    网友点评
    o