C# 使用Task.Factory.FromAsync将IAsyncResult、awit结合

2020年4月25日 0 作者 老王

最近在做读写示波器的工作,使用同步去读写示波器的话会阻塞线程,页面假死,这不能忍。然后改为异步,使用各种BeginXX和EndXX方法。由于那项目和示波器通信是有流程的,比如说先做事1,事1做完再做事2,事2做完才能做事3,这就导致要写一长串的回调方法(如下),和低版本的js一样,代码可读性实在太差了,这也不能忍!

// 看到川普
private void SeeTrump()
    Func<string> onYell = () =>
    {
        Thread.Sleep(500);
        return "喊";
    };
    Func<string> onRun = () =>
    {
        Thread.Sleep(200);
        return "跑";
    };
    onYell.BeginInvoke(yellAr => {
         // 喊完开始跑
         onRun.BeginInvoke(runAr => {
             // 跑完再做其他事

         }, null);
    }, null);
}

那怎么办,有没有优雅点的实现方式。有的,.NetFramework 4.5提供了Task.Factory.FromAsync方法,我们可以配合使用awit来优雅的实现上面的需求,既使用异步方法,又要流程化。示例代码如下(注意方法名前需要添加async关键字)。

// 看到川普
private async void SeeTrump()
{
    Func<string> onYell = () =>
    {
        Thread.Sleep(500);
        return "Yell Over";
    };
    Func<string> onRun = () =>
    {
        Thread.Sleep(200);
        return "Run Over";
    };
    Func<string> onAttack = () =>
    {
        Thread.Sleep(10000);
        return "Attack Over";
    };
    Task<string> yell = Task.Factory.FromAsync(onYell.BeginInvoke, onYell.EndInvoke, null);
    await yell;
    //logger.Debug("收到跑完的消息: " + yell.Result);
    Task<string> run =  Task.Factory.FromAsync(onRun.BeginInvoke, onRun.EndInvoke, null);
    await run;
    //logger.Debug("收到跑完的消息: " + run.Result);
    Task<string> attack=  Task.Factory.FromAsync(onAttack .BeginInvoke, onAttack .EndInvoke, null);
    await attack;
    //logger.Debug("Trump game over.");
}