The basic pattern to achieve this is to write a private function that carries out whatever operations you wish to run asynchronously. Then write a public function that starts a new thread, and pass the thread a lambda function that simply calls your internal private function. Somewhere within the internal private function, be sure to fire some events when necessary to indicate status updates or completion status.
I think the code should speak for itself. See below:
Project consists of 4 files:
EventArgs.cs
EventHandlers.cs
MyWebClient.cs
Program.cs
MyWebClient.cs:
using System;
using System.Net;
using System.Threading;
namespace WebClientAsync
{
///
/// Simple web client which implements an asynchronous download call using
/// corresponding built in .net synchronous function calls
///
public class MyWebClient
{
///
/// Event signalling that a download is completed
///
public event MyDownloadDataCompletedEventHandler DownloadDataCompleted = delegate {};
///
/// Synchronous download. Simple pssthrough to .NET WebClient
///
public byte[] DownloadDataSync(string url)
{
return new WebClient().DownloadData(url);
}
///
/// Asynchronous wrapper for function which calls blocking function and
/// also has additional logic for determining success / failure, and firing an event
public void DownloadDataAsync(string url)
{
new Thread(() => this.DownloadDataInternal( url )).Start();
}
///
/// Downloads data, which blocks calling thread. then fires an alert indicating
/// completion of a download operation. Details regarding the outcome of the
/// operation are also provided via the event arguments
private void DownloadDataInternal(string url)
{
var success = true;
try
{
this.DownloadDataSync(url);
}
catch( Exception )
{
success = false;
}
DownloadDataCompleted( this, new MyDownloadDataCompletedEventArgs(success) );
}
}
}
EventHandlers.cs:
namespace WebClientAsync
{
///
/// Handler for indicating an asynchronous download completion
///
public delegate void MyDownloadDataCompletedEventHandler( object sender, MyDownloadDataCompletedEventArgs e );
}
EventArgs.cs:
using System;
namespace WebClientAsync
{
///
/// Contains details regarding outcome of the asynchronous download operation
///
public class MyDownloadDataCompletedEventArgs : EventArgs
{
public bool Success { get; set; }
public MyDownloadDataCompletedEventArgs(bool success)
{
this.Success = success;
}
}
}
Program.cs:
using System;
using System.Threading;
using System.Windows.Forms;
namespace WebClientAsync
{
class Program
{
///
///
///
private static bool _loop = true;
///
///
///
static void Main(string[] args)
{
var url = string.Empty;
if (args.Length == 1)
{
url = args[0];
}
else
{
PrintUsage();
Environment.Exit(-1);
}
var wc = new MyWebClient();
wc.DownloadDataCompleted += DownloadDataCompleted;
wc.DownloadDataAsync(url);
while (_loop)
{
Console.WriteLine("zzz...");
Thread.Sleep(1);
}
Console.WriteLine("the download was finished so the loop ended. Press any key to exit");
Console.ReadKey();
}
///
///
///
private static void PrintUsage()
{
const string usageMessage = @"
program.exe url
e.g.
program.exe http://www.google.com/somedata.txt"
;
Console.WriteLine(usageMessage);
}
///
///
///
static void DownloadDataCompleted(object sender, MyDownloadDataCompletedEventArgs e)
{
_loop = false;
MessageBox.Show("The download completed. It was a " + (e.Success ? "Success! :)" : "Failure :("));
}
}
}
No comments:
Post a Comment