C#异步多线程几种实现方式
异步编程模式
官方说明:https://learn.microsoft.com/zh-cn/dotnet/standard/asynchronous-programming-patterns/?source=recommendations
.NET 提供了执行异步操作的三种模式:
**(1)**基于任务的异步模式 (TAP) ,该模式使用单一方法表示异步操作的开始和完成。 TAP 是在 .NET Framework 4 中引入的。 这是在 .NET 中进行异步编程的推荐方法。 C# 中的 async 和 await 关键词以及 Visual Basic 中的 Async 和 Await 运算符为 TAP 添加了语言支持。 有关详细信息,请参阅基于任务的异步模式 (TAP)。
**(2)**基于事件的异步模式 (EAP),是提供异步行为的基于事件的旧模型。 这种模式需要后缀为 Async 的方法,以及一个或多个事件、事件处理程序委托类型和 EventArg 派生类型。 EAP 是在 .NET Framework 2.0 中引入的。 建议新开发中不再使用这种模式。 有关详细信息,请参阅基于事件的异步模式 (EAP)。
**(3)**异步编程模型 (APM) 模式(也称为 IAsyncResult 模式),这是使用 IAsyncResult 接口提供异步行为的旧模型。 在这种模式下,同步操作需要 Begin 和 End 方法(例如,BeginWrite 和 EndWrite以实现异步写入操作)。 不建议新的开发使用此模式。 有关详细信息,请参阅异步编程模型 (APM)。
一、利用委托的异步调用实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Async
{
class Program
{
static void Main(string[] args)
{
//第一种方法 利用委托的异步调用实现
Console.WriteLine("===开始:当前线程:{0}===", Thread.CurrentThread.ManagedThreadId.ToString());
//委托方法
Func<string, string> ff = (a) =>
{
Console.WriteLine("当前线程:{0}", Thread.CurrentThread.ManagedThreadId.ToString());
Thread.Sleep(3000);
Console.WriteLine("异步调用{0}", a);
//Thread.CurrentThread.Suspend();
return a + ":" + a;
};
//回调函数
AsyncCallback asyncCallback = (ir) =>
{
string result = ff.EndInvoke(ir);
Console.WriteLine(result);
};
//执行
Console.WriteLine("委托异步开始==");
IAsyncResult asyncResult = ff.BeginInvoke("yibu", asyncCallback, null);
Console.WriteLine("执行完成:{0}", Thread.CurrentThread.ManagedThreadId.ToString());
Console.ReadKey();
}
}
}
二、ThreadPool线程池
说明:默认使用线程池技术,但是可用方法比较单一,只有一个QueueUserWorkItem
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Async
{
class Program
{
static void Main(string[] args)
{
//第二种 利用线程池实现
Console.WriteLine("===开始:当前线程:{0}===", Thread.CurrentThread.ManagedThreadId.ToString());
int b = 0;
try
{
ThreadPool.QueueUserWorkItem((a) =>
{
b++;
Console.WriteLine("===异步开始:当前线程:{0}===", Thread.CurrentThread.ManagedThreadId.ToString());
Console.WriteLine("1");
}, b);
}
catch (Exception ex)
{
Console.WriteLine("出现错误:{0}", ex.Message);
}
Console.WriteLine(b);
Console.WriteLine("执行完成:{0}", Thread.CurrentThread.ManagedThreadId.ToString());
Console.ReadKey();
}
}
}
三、利用 Threed类的Start()
说明:默认没有使用线程池技术,需要自己实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Async
{
class Program
{
static void Main(string[] args)
{
//第三种 利用 Threed.Start()
Console.WriteLine("===开始:当前线程:{0}===", Thread.CurrentThread.ManagedThreadId.ToString());
Func<string, string> f = (a) => a + ":" + a;
Thread thread = new Thread((a) =>
{
Console.WriteLine("===异步开始:当前线程:{0}===", Thread.CurrentThread.ManagedThreadId.ToString());
Thread.Sleep(3000);
string str = f("abc");
Console.WriteLine(str);
});
thread.Start();
Console.WriteLine("执行完成:{0}", Thread.CurrentThread.ManagedThreadId.ToString());
Console.ReadKey();
}
}
}
四、Task 类
官方说明:
Task类表示不返回值并且通常以异步方式执行的单个操作。 Task 对象是在 .NET Framework 4 中首次引入的 基于任务的异步模式 的中心组件之一。 由于对象执行的工作 Task 通常在"线程池线程"上异步执行,而不是在主应用程序线程上同步执行,因此可以使用 Status 属性以及 IsCanceled 、 IsCompleted 和 IsFaulted 属性来确定任务的状态。 通常,lambda 表达式用于指定任务要执行的工作。对于返回值的操作,请使用 Task 类。
4.1 Task定义和执行方法不分离
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Async
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===Task开始:当前线程:{0}===", Thread.CurrentThread.ManagedThreadId.ToString());
//定义异步方法
Task task = new Task(() =>
{
Console.WriteLine("===Task的异步线程:{0}===", Thread.CurrentThread.ManagedThreadId.ToString());
Thread.Sleep(2000);
});
//执行,可以先定义以后再执行,
task.Start();
Console.WriteLine("===Task结束:当前线程:{0}===", Thread.CurrentThread.ManagedThreadId.ToString());
Console.ReadKey();
}
}
}
4.2 Task定义和执行方法分离
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Async
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===Task开始:当前线程:{0}===", Thread.CurrentThread.ManagedThreadId.ToString());
//定义异步方法
Task task = new Task(() =>
{
Console.WriteLine("===Task的异步线程:{0}===", Thread.CurrentThread.ManagedThreadId.ToString());
Thread.Sleep(2000);
});
//执行,可以先定义以后再执行,
task.Start();
Console.WriteLine("===Task结束:当前线程:{0}===", Thread.CurrentThread.ManagedThreadId.ToString());
Console.ReadKey();
}
}
}
五、async/await 语法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Async
{
class Program
{
static void Main(string[] args)
{
// 第五种 await 语法
Console.WriteLine("===");
doWork();
Console.WriteLine("===");
Console.ReadKey();
}
public static async Task doWork()
{
await Task.Run(() =>
{
Console.WriteLine("当前线程:{0}", Thread.CurrentThread.ManagedThreadId.ToString());
});
}
}
}
3273

被折叠的 条评论
为什么被折叠?



