Created
May 9, 2014 04:10
-
-
Save dschenkelman/af129e88ebb996f2a152 to your computer and use it in GitHub Desktop.
Asynchronous I/O in C#: Why tasks (a.k.a. promises, futures)?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ProgramWithAPM : IRunnable | |
{ | |
private int pending; | |
private readonly object lockObject; | |
public ProgramWithAPM() | |
{ | |
this.pending = 0; | |
this.lockObject = new object(); | |
} | |
public void Run() | |
{ | |
var schenkelmanRequest = (HttpWebRequest)WebRequest.Create(new Uri("http://blogs.southworks.net/dschenkelman")); | |
var convertiRequest = (HttpWebRequest)WebRequest.Create(new Uri("http://blogs.southworks.net/mconverti")); | |
this.pending = 2; | |
schenkelmanRequest.BeginGetResponse(ar => | |
{ | |
var response = (HttpWebResponse)schenkelmanRequest.EndGetResponse(ar); | |
WriteContent(response); | |
}, schenkelmanRequest); | |
convertiRequest.BeginGetResponse(ar => | |
{ | |
var response = (HttpWebResponse)convertiRequest.EndGetResponse(ar); | |
WriteContent(response); | |
}, convertiRequest); | |
} | |
private void WriteContent(HttpWebResponse response) | |
{ | |
using (var reader = new StreamReader(response.GetResponseStream())) | |
{ | |
var content = reader.ReadToEnd(); | |
lock (this.lockObject) | |
{ | |
Console.WriteLine(content.Substring(0, 300)); | |
this.pending--; | |
if (this.pending == 0) | |
{ | |
Console.WriteLine("Downloads finished"); | |
Program.ResetEvent.Set(); | |
} | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ProgramWithAPM : IRunnable | |
{ | |
public void Run() | |
{ | |
var schenkelmanRequest = (HttpWebRequest)WebRequest.Create(new Uri("http://blogs.southworks.net/dschenkelman")); | |
var convertiRequest = (HttpWebRequest)WebRequest.Create(new Uri("http://blogs.southworks.net/mconverti")); | |
var schenkelmanTask = schenkelmanRequest.CustomGetResponseStreamAsync().ContinueWith(t => | |
{ | |
using (var reader = new StreamReader(t.Result)) | |
{ | |
var content = reader.ReadToEnd(); | |
Console.WriteLine(content.Substring(0, 300)); | |
} | |
}); | |
var convertiTask = convertiRequest.CustomGetResponseStreamAsync().ContinueWith(t => | |
{ | |
using (var reader = new StreamReader(t.Result)) | |
{ | |
var content = reader.ReadToEnd(); | |
Console.WriteLine(content.Substring(0, 300)); | |
} | |
}); | |
Task.WhenAll(convertiTask, schenkelmanTask).ContinueWith(t => | |
{ | |
Console.WriteLine("Downloads finished"); | |
Program.ResetEvent.Set(); | |
}); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ProgramWithTasksAndCancellation : IRunnable | |
{ | |
public void Run() | |
{ | |
var client = new HttpClient(); | |
var cts = new CancellationTokenSource(); | |
var convertiTask = client.GetAsync(new Uri("http://blogs.southworks.net/mconverti"), cts.Token); | |
convertiTask.ContinueWith(t => Console.WriteLine("Converti completed"), TaskContinuationOptions.NotOnCanceled); | |
var schenkelmanTask = client.GetAsync(new Uri("http://blogs.southworks.net/dschenkelman"), cts.Token); | |
schenkelmanTask.ContinueWith(t => Console.WriteLine("Schenkelman completed"), TaskContinuationOptions.NotOnCanceled); | |
Task.WhenAny(convertiTask, schenkelmanTask).ContinueWith(t => | |
{ | |
cts.Cancel(); | |
var firstTaskThatCompleted = (t.Result); | |
firstTaskThatCompleted.Result.Content.ReadAsStringAsync().ContinueWith(t2 => | |
{ | |
Console.WriteLine(t2.Result.Substring(0, 300)); | |
Console.WriteLine("Downloads finished"); | |
Program.ResetEvent.Set(); | |
}); | |
}); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ProgramWithEvents : IRunnable | |
{ | |
private int pending; | |
private readonly object lockObject; | |
public ProgramWithEvents() | |
{ | |
this.pending = 0; | |
this.lockObject = new object(); | |
} | |
public void Run() | |
{ | |
var convertiClient = new WebClient(); | |
var schenkelmanClient = new WebClient(); | |
convertiClient.OpenReadCompleted += (sender, eventArgs) => this.WriteContent(eventArgs.Result); | |
schenkelmanClient.OpenReadCompleted += (sender, eventArgs) => this.WriteContent(eventArgs.Result); | |
this.pending = 2; | |
schenkelmanClient.OpenReadAsync(new Uri("http://blogs.southworks.net/dschenkelman")); | |
convertiClient.OpenReadAsync(new Uri("http://blogs.southworks.net/mconverti")); | |
} | |
private void WriteContent(Stream stream) | |
{ | |
using (var reader = new StreamReader(stream)) | |
{ | |
var content = reader.ReadToEnd(); | |
lock (lockObject) | |
{ | |
Console.WriteLine(content.Substring(0, 300)); | |
this.pending--; | |
if (this.pending == 0) | |
{ | |
Console.WriteLine("Downloads finished"); | |
Program.ResetEvent.Set(); | |
} | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class TaskExtensions | |
{ | |
public static Task<Stream> GetResponseAsync(this HttpWebRequest webRequest) | |
{ | |
var tcs = new TaskCompletionSource<Stream>(); | |
webRequest.BeginGetResponse(ar => | |
{ | |
var response = (HttpWebResponse)webRequest.EndGetResponse(ar); | |
tcs.SetResult(response.GetResponseStream()); | |
}, webRequest); | |
return tcs.Task; | |
} | |
public static Task<Stream> TaskBasedOpenReadAsync(this WebClient webClient, Uri uri) | |
{ | |
var tcs = new TaskCompletionSource<Stream>(); | |
OpenReadCompletedEventHandler callback = null; | |
callback = (sender, args) => | |
{ | |
tcs.SetResult(args.Result); | |
webClient.OpenReadCompleted -= callback; | |
}; | |
webClient.OpenReadCompleted += callback; | |
webClient.OpenReadAsync(uri); | |
return tcs.Task; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Program | |
{ | |
public static AutoResetEvent ResetEvent = new AutoResetEvent(false); | |
static void Main(string[] args) | |
{ | |
// decide which asynchronous proposal to use | |
Run(new ProgramWithAPM()); | |
} | |
static void Run(IRunnable runnable) | |
{ | |
runnable.Run(); | |
ResetEvent.WaitOne(); | |
Console.ReadLine(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ProgramWithTasks : IRunnable | |
{ | |
public void Run() | |
{ | |
var client = new HttpClient(); | |
var convertiTask = client.GetStreamAsync(new Uri("http://blogs.southworks.net/mconverti")).ContinueWith(t => | |
{ | |
using (var reader = new StreamReader(t.Result)) | |
{ | |
var content = reader.ReadToEnd(); | |
Console.WriteLine(content.Substring(0, 300)); | |
} | |
}); | |
var schenkelmanTask = client.GetStreamAsync(new Uri("http://blogs.southworks.net/dschenkelman")).ContinueWith(t => | |
{ | |
using (var reader = new StreamReader(t.Result)) | |
{ | |
var content = reader.ReadToEnd(); | |
Console.WriteLine(content.Substring(0, 300)); | |
} | |
}); | |
Task.WhenAll(convertiTask, schenkelmanTask).ContinueWith(t => | |
{ | |
Console.WriteLine("Downloads finished"); | |
Program.ResetEvent.Set(); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment