C# 异步编程控制流
在过去的两天里,我一直在阅读有关c#async方法的文章,据我所知,与threadC# 异步编程控制流,c#,async-await,C#,Async Await,在过去的两天里,我一直在阅读有关c#async方法的文章,据我所知,与thread(threadpool.queueuserworkitem())不同的是,对异步方法的调用不会立即返回,它只会在被调用的方法遇到等待或完成(或异常)时返回 请参见下面的示例 public partial class MainWindow : Window { // . . . private async void startButton_Click(object sender, RoutedEven
(threadpool.queueuserworkitem())
不同的是,对异步方法的调用不会立即返回,它只会在被调用的方法遇到等待或完成(或异常)时返回
请参见下面的示例
public partial class MainWindow : Window
{
// . . .
private async void startButton_Click(object sender, RoutedEventArgs e)
{
// ONE
Task<int> getLengthTask = AccessTheWebAsync();
// FOUR
int contentLength = await getLengthTask;
// SIX
resultsTextBox.Text +=
String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
}
async Task<int> AccessTheWebAsync()
{
// TWO
HttpClient client = new HttpClient();
Task<string> getStringTask =
client.GetStringAsync("http://msdn.microsoft.com");
// THREE
string urlContents = await getStringTask;
// FIVE
return urlContents.Length;
}
}
公共部分类主窗口:窗口
{
// . . .
私有异步无效开始按钮单击(对象发送方,路由目标)
{
//一个
Task getLengthTask=AccessTheWebAsync();
//四
int contentLength=等待getLengthTask;
//六
结果文本框+=
格式(“\r\n下载字符串的长度:{0}.\r\n”,contentLength);
}
异步任务访问WebAsync()
{
//两个
HttpClient=新的HttpClient();
任务getStringTask=
client.GetStringAsync(“http://msdn.microsoft.com");
//三
字符串urlContents=等待getStringTask;
//五
返回urlContents.Length;
}
}
从我收集的信息来看,在上面的代码中,AccessTheWebAsync()
是同步调用的(即控件在调用时不会立即返回)。但在名为“三”的行中,运行时将返回控制
我的问题是:
AccessTheWebAsync()
做了一些计算密集型的事情,比如运行了无数次迭代的循环,那么控件只会在循环完成后返回给调用方。是这样吗首先,重要的一点是:只有在等待的任务尚未完成时,运行时才会在
await
上返回调用方
问题1:我在这里引用MSDN:
async和await关键字不会导致创建其他线程。异步方法不需要多线程,因为异步方法不在自己的线程上运行
问题2:可能在GetStringAsync
的实现中,但我们不知道这一点,也不必知道。我们知道GetStringAsync
在不阻塞线程的情况下以某种方式获得了结果,这就足够了
问题3:如果循环放在wait
关键字之前,则为“是”
问题4:引述与以前相同的段落:
您可以使用Task.Run将CPU绑定的工作移动到后台线程
您不需要使用async
和wait
关键字。例如:
private Task<int> DoSomethingAsync()
{
return Task.Run(() =>
{
// Do CPU heavy calculation here. It will be executed in the thread pool.
return 1 + 1;
});
}
private Task DoSomethingAsync()
{
返回任务。运行(()=>
{
//在这里进行CPU密集型计算。它将在线程池中执行。
返回1+1;
});
}
问题5:我将再次引用
异步方法通常包含一个或多个等待运算符,但缺少等待表达式不会导致编译器错误。如果异步方法不使用wait操作符来标记挂起点,则尽管使用了异步修饰符,该方法仍会像同步方法一样执行。编译器会对此类方法发出警告
(与前一页相同,只是不同部分)
运行时如何决定何时使用线程池或何时在调用线程中运行任务
如果存在同步上下文,并且您没有明确指定不希望在该上下文上继续(通过使用类似于wait task.configurewait(false)
)的内容),则该方法将在捕获的上下文上继续。在UI应用程序中,该上下文是UI线程,假设该方法是从UI线程调用的
在上述代码的哪些点上,将使用新线程(或线程池)
没有。除非您另外指定(请参见上文),wait
将恢复到捕获的上下文,在您的情况下,该上下文就是UI线程
如果AccessTheWebAsync()
做了一些计算密集型的事情,比如运行了无数次迭代的循环,那么控件只会在循环完成后返回给调用方。是这样吗
是的,假设循环在第一个“异步”wait
之前。(await
如果await
edTask
已经完成,那么await也可以是“同步的”。)
在异步函数中,有没有一种方法可以立即返回控件,然后在后台线程中继续工作
为此,应该使用Task.Run()
调用一个不带wait的异步方法(假设可能)与调用一个非异步方法相同吗
这是可能的,编译器将警告您该方法将完全同步执行