vs2019创建.net core3.1 的控制台应用程序
执行以下代码:
using System; using System.Diagnostics; using System.Threading; namespace ConsoleApp3 { /// <summary> /// 委托必须和要调用的异步方法有相同的签名 /// </summary> /// <param name="callDuration">sleep时间</param> /// <param name="threadId">当前线程id</param> /// <returns></returns> public delegate string AsyncMethodCaller(int callDuration, out int threadId); class Program { /// <summary> /// 主函数 /// </summary> /// <param name="args"></param> static void Main(string[] args) { AsyncMethodCaller caller = new AsyncMethodCaller(TestMethodAsync); int threadid = 0; //开启异步操作 IAsyncResult result = caller.BeginInvoke(3000, out threadid, null, null); for (int i = 0; i < 10; i++) { Console.WriteLine("其它业务" + i.ToString()); } //调用EndInvoke,等待异步执行完成 Console.WriteLine("等待异步方法TestMethodAsync执行完成"); string res = caller.EndInvoke(out threadid, result); Console.WriteLine("Completed!"); Console.WriteLine(res); Console.Read(); } /// <summary> /// 与委托对应的方法 /// </summary> /// <param name="callDuration"></param> /// <param name="threadId"></param> /// <returns></returns> static string TestMethodAsync(int callDuration, out int threadId) { Stopwatch sw = new Stopwatch(); sw.Start(); Console.WriteLine("异步TestMethodAsync开始"); for (int i = 0; i < 5; i++) { // 模拟耗时操作 Thread.Sleep(callDuration); Console.WriteLine("TestMethodAsync:" + i.ToString()); } sw.Stop(); threadId = Thread.CurrentThread.ManagedThreadId; return string.Format("耗时{0}ms.", sw.ElapsedMilliseconds.ToString()); } } }
IAsyncResult result = caller.BeginInvoke(3000, out threadid, null, null);
所在行提示错误
System.PlatformNotSupportedException HResult=0x80131539 Message=Operation is not supported on this platform. Source=ConsoleApp3 StackTrace: at ConsoleApp3.AsyncMethodCaller.BeginInvoke(Int32 callDuration, Int32& threadId, AsyncCallback callback, Object object) at ConsoleApp3.Program.Main(String[] args) in C:Userspxmsource eposConsoleApp3ConsoleApp3Program.cs:line 26
原因
The Asynchronous Programming Model (APM) (using IAsyncResult and BeginInvoke) is no longer the preferred method of making asynchronous calls. The Task-based Asynchronous Pattern (TAP) is the recommended async model as of .NET Framework 4.5. Because of this, and because the implementation of async delegates depends on remoting features not present in .NET Core, BeginInvoke and EndInvoke delegate calls are not supported in .NET Core. This is discussed in GitHub issue dotnet/corefx #5940.
异步编程模型(APM)(使用IAsyncResult和BeginInvoke)不再是异步调用的优选方法。从.NET Framework 4.5开始,基于任务的异步模式(TAP)是推荐的异步模型。因此,而且由于异步委托的实现取决于远程处理但.NET Core不存在的功能,BeginInvoke和EndInvoke委托调用不.NET Core支持。GitHub问题 dotnet/corefx#5940 中对此进行了讨论
Async delegates are not in .NET Core for several reasons:
- Async delegates use deprecated IAsyncResult-based async pattern. This pattern is generally not supported throughout .NET Core base libraries, e.g. System.IO.Stream does not have IAsyncResult-based overloads for Read/Write methods in .NET Core.
- Async delegates depend on remoting (System.Runtime.Remoting) under the hood. Remoting is not in .NET Core - implementation of async delegates without remoting would be challenging.
解决办法
改为基于任务的异步模式Task.Run
using System; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; namespace ConsoleApp3 { /// <summary> /// 委托必须和要调用的异步方法有相同的签名 /// </summary> /// <param name="callDuration">sleep时间</param> /// <param name="threadId">当前线程id</param> /// <returns></returns> public delegate string AsyncMethodCaller(int callDuration, out int threadId); class Program { /// <summary> /// 主函数 /// </summary> /// <param name="args"></param> static void Main(string[] args) { AsyncMethodCaller caller = new AsyncMethodCaller(TestMethodAsync); int threadid = 0; //开启异步操作 //IAsyncResult result = caller.BeginInvoke(3000, out threadid, null, null); var workTask = Task.Run(() => caller.Invoke(3000, out threadid)); for (int i = 0; i < 10; i++) { Console.WriteLine("其它业务" + i.ToString()); } //调用EndInvoke,等待异步执行完成 Console.WriteLine("等待异步方法TestMethodAsync执行完成"); //string res = caller.EndInvoke(out threadid, result); string res = workTask.Result; Console.WriteLine("Completed!"); Console.WriteLine(res); Console.Read(); } /// <summary> /// 与委托对应的方法 /// </summary> /// <param name="callDuration"></param> /// <param name="threadId"></param> /// <returns></returns> static string TestMethodAsync(int callDuration, out int threadId) { Stopwatch sw = new Stopwatch(); sw.Start(); Console.WriteLine("异步TestMethodAsync开始"); for (int i = 0; i < 5; i++) { // 模拟耗时操作 Thread.Sleep(callDuration); Console.WriteLine("TestMethodAsync:" + i.ToString()); } sw.Stop(); threadId = Thread.CurrentThread.ManagedThreadId; return string.Format("耗时{0}ms.", sw.ElapsedMilliseconds.ToString()); } } }
参考:
1.Migrating Delegate.BeginInvoke Calls for .NET Core