C# 多线程 04-使用任务平行库 04-将 APM 模式转换为任务
🏷️ 《C# 多线程》
将 APM 模式转换为任务
关于 APM(Asynchronous Programming Model:异步编程模型)可以参考 01-在线程池中调用委托。
本节介绍将 APM 转换为 Task。
csharp
/// <summary>
/// 将 APM 模式转换为任务
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
int threadId;
AsynchronousTask d = Test;
IncompatibleAsynchronousTask e = Test;
// 将 APM 转换为 TPL 的关键是 Task<T>.Factory.FromAsync 方法
// 其中 T 为异步操作结果的类型
// 该方法有多个重载。
Console.WriteLine("Option 1");
// 这种方法可以指定回调函数
Task<string> task = Task<string>.Factory.FromAsync(
d.BeginInvoke(
"AsyncTaskThread",
Callback,
"a delegate asynchronous call"),
d.EndInvoke);
task.ContinueWith(t => Console.WriteLine($"Callback is finished, now running a continuation! Result: {t.Result}"));
while (!task.IsCompleted)
{
Console.WriteLine(task.Status);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
Console.WriteLine(task.Status);
Thread.Sleep(TimeSpan.FromSeconds(1));
Console.WriteLine("------------------------------------");
Console.WriteLine();
Console.WriteLine("Option 2");
// 这种方法不能直接指定回调函数
// 如果需要,可以使用 Task.ContinueWith 方法执行回调函数。
task = Task<string>.Factory.FromAsync(
d.BeginInvoke,
d.EndInvoke,
"AsyncTaskThread",
"a delegate asynchronous call");
task.ContinueWith(t => Console.WriteLine($"Task is completed, now running a continuation! Result: {t.Result}"));
while (!task.IsCompleted)
{
Console.WriteLine(task.Status);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
Console.WriteLine(task.Status);
Thread.Sleep(TimeSpan.FromSeconds(1));
Console.WriteLine("------------------------------------");
Console.WriteLine();
Console.WriteLine("Option 3");
// 这里的异步方法带有 out 参数,导致 EndInvoke 的签名和 FromAsync 的签名不一致
// 这里展示了一个小技巧,使用 lambda 表达式封装了 EndInvoke 方法
IAsyncResult ar = e.BeginInvoke(out threadId, Callback, "a delegate asynchronous call");
task = Task<string>.Factory.FromAsync(ar, _ => e.EndInvoke(out threadId, ar));
task.ContinueWith(t => Console.WriteLine($"Task is completed, now running a continuation! Result: {t.Result}, ThreadId: {threadId}"));
while (!task.IsCompleted)
{
Console.WriteLine(task.Status);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
Console.WriteLine(task.Status);
Thread.Sleep(TimeSpan.FromSeconds(1));
Console.ReadLine();
}
delegate string AsynchronousTask(string threadName);
delegate string IncompatibleAsynchronousTask(out int threadId);
static void Callback(IAsyncResult ar)
{
Console.WriteLine("Starting a callback ...");
Console.WriteLine($"State passed to a callback: {ar.AsyncState}");
Console.WriteLine($"Is thread pool thread: {Thread.CurrentThread.IsThreadPoolThread}");
Console.WriteLine($"Thread pool worker thread id: {Thread.CurrentThread.ManagedThreadId}");
}
static string Test(string threadName)
{
Console.WriteLine("Starting...");
Console.WriteLine($"Is thread pool thread: {Thread.CurrentThread.IsThreadPoolThread}");
Thread.Sleep(TimeSpan.FromSeconds(2));
Thread.CurrentThread.Name = threadName;
return $"Thread anme: {Thread.CurrentThread.Name}";
}
static string Test(out int threadId)
{
Console.WriteLine("Starting...");
Console.WriteLine($"Is thread pool thread: {Thread.CurrentThread.IsThreadPoolThread}");
Thread.Sleep(TimeSpan.FromSeconds(2));
threadId = Thread.CurrentThread.ManagedThreadId;
return $"Thread pool worker thread id was: {threadId}";
}
打印结果
txt
Option 1
WaitingForActivation
Starting...
Is thread pool thread: True
WaitingForActivation
WaitingForActivation
WaitingForActivation
WaitingForActivation
Starting a callback ...
State passed to a callback: a delegate asynchronous call
Is thread pool thread: True
Thread pool worker thread id: 3
Callback is finished, now running a continuation! Result: Thread anme: AsyncTask
Thread
RanToCompletion
------------------------------------
Option 2
WaitingForActivation
Starting...
Is thread pool thread: True
WaitingForActivation
WaitingForActivation
WaitingForActivation
WaitingForActivation
Task is completed, now running a continuation! Result: Thread anme: AsyncTaskThr
ead
RanToCompletion
------------------------------------
Option 3
WaitingForActivation
Starting...
Is thread pool thread: True
WaitingForActivation
WaitingForActivation
WaitingForActivation
WaitingForActivation
Starting a callback ...
State passed to a callback: a delegate asynchronous call
Is thread pool thread: True
Thread pool worker thread id: 3
Task is completed, now running a continuation! Result: Thread pool worker thread
id was: 3, ThreadId: 3
RanToCompletion