分类目录归档:OOP

C# 异步

异步函数简介
一般指 async 修饰符声明得、可包含await表达式得方法或匿名函数。

声明方式
异步方法的声明语法与其他方法完全一样, 只是需要包含 async 关键字。async可以出现在返回值之前的任何位置, 如下示例:

    async public static void GetInfoAsync()
        {
           //...
        }

    public async static void GetInfoAsync()
        {
           //...
        }

    public static async void GetInfoAsync()
        {
            //...
        }

异步方法的返回类型
异步函数的返回类型只能为: void、Task、Task
Task: 代表一个返回值T类型的操作。
Task: 代表一个无返回值的操作。
void: 为了和传统的事件处理程序兼容而设计。

await(等待)
await等待的是什么? 可以是一个异步操作(Task)、亦或者是具备返回值的异步操作(Task)的值, 如下:

    public async static void GetInfoAsync()
        {
            await GetData(); // 等待异步操作, 无返回值
            await GetData<int>(1); //等待异步操作, 返回值 int
        }

    static Task GetData()
        {
            //...
            return null;
        }

    static Task<T> GetData<T>(int a)
        {
            //...
            return null;
        }

注: await 最终操作的是一个值, 当然, 也可以是无值, 如上GetData() , 否则就是一个 Task 如上: GetData()

原文链接:https://www.cnblogs.com/zh7791/p/9951478.html
———————————————————————-

async用来修饰方法,表明这个方法是异步的,声明的方法的返回类型必须为:void或Task或Task。返回类型为Task的异步方法中无需使用return返回值,而返回类型为Task的异步方法中必须使用return返回一个TResult的值
await必须用来修饰Task或Task,而且只能出现在已经用async关键字修饰的异步方法中。
async/await必须成对出现才有意义,假如一个方法声明为async,但却没有使用await关键字,则这个方法在执行的时候就被当作同步方法,这时编译器也会抛出警告提示async修饰的方法中没有使用await,将被作为同步方法使用。
async关键字表明可以在方法内部使用await关键字,方法在执行到await前都是同步执行的,运行到await处就会挂起,并返回到Main方法中,直到await标记的Task执行完毕,才唤醒回到await点上,继续向下执行。

static void Main(string[] args)
{
    Console.WriteLine("开始获取博客园首页字符数量");
    Task<int> task1 = CountCharsAsync("http://www.cnblogs.com");
    Console.WriteLine("开始获取百度首页字符数量");
    Task<int> task2 = CountCharsAsync("http://www.baidu.com");
 
    Console.WriteLine("Main方法中做其他事情");
 
    Console.WriteLine("博客园:" + task1.Result);
    Console.WriteLine("百度:" + task2.Result);
}
 
static async Task<int> CountCharsAsync(string url)
{
    WebClient wc = new WebClient();
    string result = await wc.DownloadStringTaskAsync(new Uri(url));
    return result.Length;
}
static void Main(string[] args)
{
    Console.WriteLine("-------主线程启动-------");
    Task<int> task = GetLengthAsync();
    Console.WriteLine("Main方法做其他事情");
    Console.WriteLine("Task返回的值" + task.Result);
    Console.WriteLine("-------主线程结束-------");
}
 
static async Task<int> GetLengthAsync()
{
    Console.WriteLine("GetLengthAsync Start");
    string str = await GetStringAsync();
    Console.WriteLine("GetLengthAsync End");
    return str.Length;
}
 
static Task<string> GetStringAsync()
{
    return Task<string>.Run(() => { Thread.Sleep(2000); return "finished"; });
}

异步和同步的区别

“同步”就好比:你去外地上学(人生地不熟),突然生活费不够了;此时你决定打电话回家,通知家里转生活费过来,可是当你拨出电话时,对方一直处于待接听状态(即:打不通,联系不上),为了拿到生活费,你就不停的oncall、等待,最终可能不能及时要到生活费,导致你今天要做的事都没有完成,而白白花掉了时间。
“异步”就是:在你打完电话发现没人接听时,猜想:对方可能在忙,暂时无法接听电话,所以你发了一条短信(或者语音留言,亦或是其他的方式)通知对方后便忙其他要紧的事了;这时你就不需要持续不断的拨打电话,还可以做其他事情;待一定时间后,对方看到你的留言便回复响应你,当然对方可能转钱也可能不转钱。但是整个一天下来,你还做了很多事情。 或者说你找室友临时借了一笔钱,又开始happy的上学时光了。
简而言之,言而总之:同步就是我强依赖你(对方),我必须等到你的回复,才能做出下一步响应。即我的操作(行程)是顺序执行的,中间少了哪一步都不可以,或者说中间哪一步出错都不可以,类似于编程中程序被解释器顺序执行一样;同时如果我没有收到你的回复,我就一直处于等待、也就是阻塞的状态。 异步则相反,我并不强依赖你,我对你响应的时间也不敏感,无论你返回还是不返回,我都能继续运行;你响应并返回了,我就继续做之前的事情,你没有响应,我就做其他的事情。也就是说我不存在等待对方的概念,我就是非阻塞的。
从上面的例子来看:同步似乎等价于阻塞,异步则等价于非阻塞。其实有些狭义,但不可否认的是,在一定情况下,确实可以这么认为;因为同步一定存在着阻塞状态,而异步一定不存在非阻塞的状态。 但是不是就是说 同步调用 == 阻塞调用呢?然并不是;阻塞和非阻塞强调的是程序在等待调用结果(消息,返回值)时的状态. 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。 对于同步调用来说,很多时候当前线程还是激活的状态,只是从逻辑上当前函数没有返回而已,即同步等待时什么都不干,白白占用着资源。同步和异步强调的是消息通信机制 (synchronous communication/ asynchronous communication)。所谓同步,就是在发出一个”调用”时,在没有得到结果之前,该“调用”就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由“调用者”主动等待这个“调用”的结果。而异步则是相反,”调用”在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在”调用”发出后,”被调用者”通过状态、通知来通知调用者,或通过回调函数处理这个调用。

原文链接:https://www.zhihu.com/question/19732473/answer/20851256