如何将await/async与同步代码一起使用? [英] How do I use await/async with synchronous code?

查看:455
本文介绍了如何将await/async与同步代码一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用await/async来使一些同步代码异步.例如,这可以工作并取消阻止UI线程:

I'm trying to use await/async in order to make some synchronous code asynchronous. For example, this works and unblocks the UI thread:

private async void button1_Click(object sender, EventArgs e)
{
    var task = DoRequestAsync();
    textBox1.Text = "starting async task";
    var text = await task;
    textBox1.Text = text;
}

private async Task<string> DoRequestAsync()
{
    try
    {
        var client = new HttpClient();
        client.Timeout = new TimeSpan(0, 0, 0, 5);
        await client.GetAsync("http://123.123.123.123"); // force a timeout exception
    }
    catch (Exception e)
    {
    }

    return "done!";
}

但这不会,并且会挂起UI线程:

But this doesn't, and will hang the UI thread:

private async void button1_Click(object sender, EventArgs e)
{
    var task = DoRequestAsync();
    textBox1.Text = "starting async task";
    var text = await task;
    textBox1.Text = text;
}

private async Task<string> DoRequestAsync()
{
    try
    {
        var request = WebRequest.Create("http://123.123.123.123");
        request.Timeout = 5000;
        request.GetResponse(); // force a timeout exception
    }
    catch (Exception e)
    {
    }

    return "done!";
}

我试图理解为什么会这样.我的印象是var task = DoRequestAsync()将创建一个新线程并异步运行该方法中的所有内容,但事实并非如此.

I'm trying to understand why this is the case. I was under the impression that var task = DoRequestAsync() will create a new thread and run everything in the method asynchronously, but that appears to not be the case.

我可以使用它来使其工作:

I can use this to make it work:

await Task.Run(() => {
    var request = WebRequest.Create("http://123.123.123.123");
    request.Timeout = 5000;
    request.GetResponse();
});

但是,这似乎有点棘手,我不确定这是否是解决此问题的正确方法.有人知道我如何才能使用Tasks和async/await以异步方式运行一堆同步代码吗?

But this seems a bit hacky and I'm not sure if it's the right solution to this issue. Does anybody know how I can just run a bunch of synchronous code in an asynchronous way using Tasks and async/await?

推荐答案

那是正确的解决方案. WebRequest.GetResponse不是异步方法,因此它不会返回Task.它不能异步运行.

That's the right solution. WebRequest.GetResponse is not an async method therefore it does not return a Task. It cannot run asynchronously.

实际上,您所拥有的是(Task.Run)可以获得的最正确,最简捷的解决方案.

Actually, what you have there is the most correct and shorthand solution you can get (with Task.Run).

我的印象是var task = DoRequestAsync()将 创建一个新线程并异步运行方法中的所有内容, 但事实并非如此.

I was under the impression that var task = DoRequestAsync() will create a new thread and run everything in the method asynchronously, but that appears to not be the case.

这不是魔术.为了使其异步运行,必须在您的异步方法中创建一个新的Task(非线程),或者必须等待一个或多个方法),该Task返回TaskTask<T>void(这是为了事件处理程序.)

It's not magic. In order for it to run asynchronously, a new Task (not thread) must be created in your async method or it must await on one or more methods)that return either Task, Task<T> or void (this is for event handlers).

您在方法return "done!";中的最后一条语句仅返回完成的Task<string>,结果为完成".

Your last statement in the method return "done!"; just returns a completed Task<string> with result "done".

作为旁注,这就是HttpClient成为事实上的类HTTP请求的原因,尤其是用于与Web API互操作以及用于通用GET/POST/etc:它具有异步支持.

As a side note, this is why HttpClient is becoming the de facto class HTTP requests, especially for interoperating with web APIs but also for general purpose GETs/POSTs/etc: it has async support.

任务还支持包装Begin */End *函数(与以前的

Tasks also have support to wrap Begin*/End* functions (conforming to the former asynchronous programming model - APM). You can also do:

try
{
    var request = WebRequest.Create("http://123.123.123.123");
    request.Timeout = 5000;
    await Task.Factory.FromAsync(request.BeginGetResponse(), request.EndGetResponse, null); // force a timeout exception
}
catch (Exception e)
{
    //TODO handle exception here
}

这篇关于如何将await/async与同步代码一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆