您的位置:首页 > 编程语言 > C#

C# - Truth of Facts - threading and await/async

2013-01-22 00:00 495 查看
It is lured to believe that async and await will take care of threading underneather, because as the name suggests that there must be something related to threading and the CLR runtime must be taking care of the threading underneath so you get real asynchronous.

However, from the MSDN prescription (link http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx#BKMK_Threads) ,

Async methods are intended to be non-blocking operations. An await expression in an async method doesn’t block the current thread while the awaited task is running. Instead, the expression signs up the rest of the method as a continuation and returns control to the caller of the async method.

The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active. You can use Task.Run to move CPU-bound work to a background thread, but a background thread doesn't help with a process that's just waiting for results to become available.

The async-based approach to asynchronous programming is preferable to existing approaches in almost every case. In particular, this approach is better than BackgroundWorker for IO-bound operations because the code is simpler and you don't have to guard against race conditions. In combination with Task.Run, async programming is better than BackgroundWorker for CPU-bound operations because async programming separates the coordination details of running your code from the work that Task.Run transfers to the threadpool.
We know that it does not create additional managed thread or use any thread pool for the asyn operation, as can be corroborated by the test below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

// Add a using directive and a reference for System.Net.Http;
using System.Net.Http;

using System.Diagnostics;

namespace AsyncFirstExample
{
public partial class MainWindow : Window
{
// Mark the event handler with async so you can use await in it.
private async void StartButton_Click(object sender, RoutedEventArgs e)
{
// Call and await separately.
//Task<int> getLengthTask = AccessTheWebAsync();
//// You can do independent work here.
//int contentLength = await getLengthTask;

int contentLength = await AccessTheWebAsync();

var currentThread = System.Threading.Thread.CurrentThread.ManagedThreadId;

resultsTextBox.Text +=
String.Format("\r\nLength of the downloaded string: {0}. -- thread id: {1}\r\n", contentLength, currentThread);
System.Diagnostics.Debug.WriteLine(String.Format("\r\nLength of the downloaded string: {0}. -- thread id: {1}\r\n", contentLength, currentThread));

}

// Three things to note in the signature:
//  - The method has an async modifier.
//  - The return type is Task or Task<T>. (See "Return Types" section.)
//    Here, it is Task<int> because the return statement returns an integer.
//  - The method name ends in "Async."
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();

// GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();

var currentThread = System.Threading.Thread.CurrentThread.ManagedThreadId;
string preUrlContents = string.Format("\r\n before await in AccessTheWebAsync, thread id: {0}", currentThread);

// Debug output
System.Diagnostics.Debug.WriteLine(preUrlContents);

// The await operator suspends AccessTheWebAsync.
//  - AccessTheWebAsync can't continue until getStringTask is complete.
//  - Meanwhile, control returns to the caller of AccessTheWebAsync.
//  - Control resumes here when getStringTask is complete.
//  - The await operator then retrieves the string result from getStringTask.
string urlContents = await getStringTask;

currentThread = System.Threading.Thread.CurrentThread.ManagedThreadId;

string postUrlContents = string.Format("\r\n after the await in AccessTheWebAsync, thread id: {0}", currentThread);
System.Diagnostics.Debug.WriteLine(postUrlContents);

// The return statement specifies an integer result.
// Any methods that are awaiting AccessTheWebAsync retrieve the length value.
return urlContents.Length;
}

void DoIndependentWork()
{
resultsTextBox.Text += "Working . . . . . . .\r\n";
}
}
}

// Sample Output:

// Working . . . . . . .

// Length of the downloaded string: 41564.
And for what it is worth, the Xaml definition is follow.
<Window x:Class="AsyncFirstExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Async Example" Height="350" Width="592">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16*"/>
<ColumnDefinition Width="161*"/>
<ColumnDefinition Width="111*"/>
</Grid.ColumnDefinitions>
<Button x:Name="startButton" Content="Start
" HorizontalAlignment="Left" Margin="217,10,0,0" VerticalAlignment="Top" Width="75" Height="24"  Click="StartButton_Click" Grid.Column="1"/>
<TextBox x:Name="resultsTextBox" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Bottom" Width="576" Height="263" FontFamily="Lucida Console" FontSize="10" VerticalScrollBarVisibility="Visible" Grid.ColumnSpan="3"/>

</Grid>
</Window>

when you run the code, you will see from the debug output window

before await in AccessTheWebAsync, thread id: 9

after the await in AccessTheWebAsync, thread id: 9

Length of the downloaded string: 51894. -- thread id: 9
As you can see, that all the method will display the managed thread id "9".
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c# .net