Last active
May 30, 2022 13:01
-
-
Save guojianwei001/95a3374705293399d562a4caca18dd20 to your computer and use it in GitHub Desktop.
Convert old BeginRead/EndRead asyn method to async/await method; implete a simple FromAsync similar to Task.Factory.FromAsync
This file contains 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
#nullable enable | |
using System; | |
using System.IO; | |
using System.Threading.Tasks; | |
namespace AsyncAwaitPlay | |
{ | |
class Program | |
{ | |
/* | |
*References: | |
* https://devblogs.microsoft.com/dotnet/migrating-delegate-begininvoke-calls-for-net-core/ | |
* https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/interop-with-other-asynchronous-patterns-and-types | |
* https://gist.github.com/emoacht/aa1f919a0dc6b6906d41 | |
* https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcompletionsource-1?view=net-6.0 | |
*/ | |
static async Task Main(string[] args) | |
{ | |
// case 1: By Task.Factory.FromAsync, convert the old style of async beginMethod/EndMethod to async/await style | |
var result = await ReadFileAsync("testfile.txt"); | |
Console.WriteLine(result); // content should be: "This is a test file." | |
// case 2: Implement a simple FromAsync methold similar as Task.Factory.FromAsync, do this conversion | |
//var result = await MyReadFileAsync("testfile.txt"); | |
//Console.WriteLine(result); // content should be: "This is a test file." | |
Console.ReadKey(); | |
} | |
static async Task<string> ReadFileAsync(string filePath) | |
{ | |
if (!File.Exists(filePath)) | |
return null; | |
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) | |
{ | |
var buff = new byte[fs.Length]; | |
return await Task.Factory.FromAsync(fs.BeginRead, fs.EndRead, buff, 0, buff.Length, TaskCreationOptions.None) | |
.ContinueWith(_ => | |
{ | |
using (var ms = new MemoryStream(buff)) | |
using (var sr = new StreamReader(ms)) | |
return sr.ReadToEnd(); | |
}); | |
} | |
} | |
static async Task<string> MyReadFileAsync(string filePath) | |
{ | |
if (!File.Exists(filePath)) | |
return null; | |
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) | |
{ | |
var buff = new byte[fs.Length]; | |
return await FromAsync(fs.BeginRead, fs.EndRead, buff, 0, buff.Length, TaskCreationOptions.None) | |
.ContinueWith(_ => | |
{ | |
using (var ms = new MemoryStream(buff)) | |
using (var sr = new StreamReader(ms)) | |
return sr.ReadToEnd(); | |
}); | |
} | |
} | |
static Task<TResult> FromAsync<TArg1, TArg2, TArg3, TResult>( | |
Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod, | |
Func<IAsyncResult, TResult> endMethod, | |
TArg1 arg1, | |
TArg2 arg2, | |
TArg3 arg3, | |
object? state) | |
{ | |
var tcs1 = new TaskCompletionSource<TResult>(); | |
beginMethod(arg1, arg2, arg3, asyncResult => | |
{ | |
if (asyncResult.CompletedSynchronously == false) | |
{ | |
var result = endMethod(asyncResult); | |
tcs1.SetResult(result); | |
} | |
}, state); | |
return tcs1.Task; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment