Introduction
This article mainly focuses on demonstrating how the async
and await
keywords combined with lambda expressions in C# 5.0 are going to minimize
the lines of code and how efficient they are.
Before going further, let me list the prerequisites.
- The given code works only with .NET 4.5.
- This solution file was built in Visual Studio 2011 Developer View version.
- I used Google Image API
for getting image URLs of the search keyword.
- Check for proxy and internet settings since the code uses internet to get the data.
Hence get all the things in place before trying out the code :)
Background
For reference, remember that the await
keyword is used to mark asynchronous calls so that you don’t need to create callback functions
anymore and can write code in the same way as if it were synchronous. The compiler will do all of the heavy lifting for you. The async
keyword
must be presented in the signature of the method that makes the asynchronous calls. Briefly, you can use the await
keyword only if the async
keyword
is in the method signature. The same is true for lambda expressions.
In the below example, I am going to show all the above said possibilities.
Using the Code
The UI code in XAML is quite simple and very much self explanatory. So let us go for the core logic.
The core logic of the program rests with the search button click where in the following tasks are performed:
Task 1: Initialize GimageSearchClient
and begin search.
Task 2: Pass four parameters to beginsearch
such that the first among them is the search keyword to get images, the second one is the number
of results to display, the third and very important one is the lambda expression which returns the results of GimageSearchClient
and assigns the same
to wrapPanel
through a dispatcher. The final param is the AsyncState
which is any way null.
private void btnSubmit_Click(object sender, RoutedEventArgs e)
{
wrapPanel.Children.Clear();
GimageSearchClient client = new GimageSearchClient("http://www.google.com");
IList<IImageResult> results ;
IAsyncResult result= client.BeginSearch(
textSearch.Text.Trim(), int.Parse(textResult.Text), ((arResult) => {
results = client.EndSearch(arResult);
Dispatcher.Invoke(DispatcherPriority.Send,
(Action<IList<IImageResult>>)(async (data) =>
{
for (int i = 0; i < results.Count; i++)
{
Image img = new Image{
Source = await DownloadImage(results[i].TbImage.Url),
Stretch = Stretch.UniformToFill,
StretchDirection = StretchDirection.DownOnly,
};
wrapPanel.Children.Add(img);
}
}),null);
}),
null );
}
Observation
The key function here is to download the image which is done by await DownloadImage
in the above code which is again a single line function:
private async Task<BitmapImage> DownloadImage(string url)
{
return byteArrayToImage(await new WebClient().DownloadDataTaskAsync(url));
}
public BitmapImage byteArrayToImage(byte[] byteArrayIn)
{
BitmapImage myBitmapImage;
using (MemoryStream stream = new MemoryStream(byteArrayIn))
{
myBitmapImage = new BitmapImage();
myBitmapImage.BeginInit();
myBitmapImage.StreamSource = stream;
myBitmapImage.CacheOption = BitmapCacheOption.OnLoad;
myBitmapImage.EndInit();
}
return myBitmapImage;
}
Here the download image uses the Async CTP function DownloadDataTaskAsync
which downloads the image in terms of bytes.
Hence a byteArrayToImage
utility function is written to convert the same in BitmapImage
format.
The interesting point here is the await
keyword, which is used both for the DownloadDataTaskAsync
function and the lambda expression used.
Points of Interest
Hence to be simple, with C# 5.0 coming out, the code for which once we used to write pages and pages is going to be in word count, with the same functionality.