저는 최근에 직장도 구해야 하고 상사 회사의 일도 처리해야 해서 매우 바빴습니다. 오늘은 회사에서 바쁜 일정을 쉬면서 .NET에서의 비동기 호출 함수 구현 방법을 정리했습니다. 이 블로그 글을 쓰기 전에 DebugLZQ가 이 글을 쓰기 전에 모든 샘플 코드를 작성했습니다. , 그래서 나는 코드로 말할 수 있습니다.
이 기사의 내용은 비동기 호출 방법을 명확하게 설명하기 위해 가장 간결한 코드를 사용하는 것을 목표로 합니다. 자, 방해하지 마세요~
lz's 이전 기사에서는 주로 이해의 관점에서 비동기에 대해 간략하게 설명했습니다. 이 기사에서는 주로 구체적인 구현 방법에 대해 설명합니다. 비동기 프로그래밍을 구현하기 위해 선택할 수 있는 네 가지 방법이 있습니다. 이러한 네 가지 유형의 요청은 실제로 "대기"와 "콜백"이라는 두 가지 범주로 구분되는 네 가지 비동기 호출 모드에 해당합니다. 4가지 메소드에 대한 자세한 설명은 여기서는 다루지 않겠습니다.
첫 번째 메소드: BeginEnvoke EndEnvoke 메소드는 "wait"에 속합니다. " 수업.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace 异步调用实现方法汇总 { /// <summary> /// 异步调用方法总结: /// 1.BeginEnvoke EndEnvoke /// 当使用BeginInvoke异步调用方法时,如果方法未执行完,EndInvoke方法就会一直阻塞,直到被调用的方法执行完毕 /// </summary> class Program { public delegate void PrintDelegate(string s); static void Main(string[] args) { PrintDelegate printDelegate = Print; Console.WriteLine("主线程"); IAsyncResult result= printDelegate.BeginInvoke("Hello World.", null, null); Console.WriteLine("主线程继续执行..."); //当使用BeginInvoke异步调用方法时,如果方法未执行完,EndInvoke方法就会一直阻塞,直到被调用的方法执行完毕 printDelegate.EndInvoke(result); Console.WriteLine("Press any key to continue..."); Console.ReadKey(true); } public static void Print(string s) { Console.WriteLine("异步线程开始执行:"+s); Thread.Sleep(5000); } } }
프로그램 실행 결과는 다음과 같습니다.
두 번째 방법: WaitOne. 또한 "대기" 범주에 속합니다.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace 异步调用实现方法汇总2 { /// <summary> /// 异步调用方法总结: /// 2.WaitOne /// 可以看到,与EndInvoke类似,只是用WaitOne函数代码了EndInvoke而已。 /// </summary> class Program { public delegate void PrintDelegate(string s); static void Main(string[] args) { PrintDelegate printDelegate = Print; Console.WriteLine("主线程"); IAsyncResult result = printDelegate.BeginInvoke("Hello World.", null, null); Console.WriteLine("主线程继续执行..."); result.AsyncWaitHandle.WaitOne(-1, false); Console.WriteLine("Press any key to continue..."); Console.ReadKey(true); } public static void Print(string s) { Console.WriteLine("异步线程开始执行:" + s); Thread.Sleep(5000); } } }
프로그램 실행 결과는 다음과 같습니다.
세 번째 방법은 폴링(Polling)입니다. 또한 "대기" 범주에 속합니다.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace 异步调用实现方法汇总3 { /// <summary> /// 异步调用方法总结: /// 3.轮询 /// 之前提到的两种方法,只能等下异步方法执行完毕, /// 在完毕之前没有任何提示信息,整个程序就像没有响应一样,用户体验不好, /// 可以通过检查IasyncResult类型的IsCompleted属性来检查异步调用是否完成, /// 如果没有完成,则可以适时地显示一些提示信息 /// </summary> class Program { public delegate void PrintDelegate(string s); static void Main(string[] args) { PrintDelegate printDelegate = Print; Console.WriteLine("主线程:"+Thread.CurrentThread.ManagedThreadId ); IAsyncResult result = printDelegate.BeginInvoke("Hello world.", null, null); Console.WriteLine("主线程:" + Thread.CurrentThread.ManagedThreadId + ",继续执行..."); while (!result.IsCompleted) { Console.WriteLine("."); Thread.Sleep(500); } Console.WriteLine("主线程:" + Thread.CurrentThread.ManagedThreadId + " Press any key to continue..."); Console.ReadKey(true); } public static void Print(string s) { Console.WriteLine("当前线程:" + Thread.CurrentThread.ManagedThreadId + s); Thread.Sleep(5000); } } }
프로그램 실행 결과는 다음과 같습니다.
네 번째 방법: 콜백. 확실히 "콜백" 범주에 속합니다. 추천하다! ! ! !
이전 세 가지 메소드는 비동기 메소드가 완료되기를 기다린 후에만 실행 결과를 얻을 수 있으며, 그 동안 메인 스레드는 대기 상태에 있습니다. 콜백과 콜백의 가장 큰 차이점은 BeginInvoke를 호출할 때 콜백 메서드가 제공되는 한, 비동기 스레드가 작업을 완료할 때까지 메인 스레드가 기다릴 필요가 없다는 것입니다. 비동기 스레드는 우리가 제공한 콜백 메서드를 적극적으로 호출합니다. 작업이 완료된 후 콜백 메소드에서 적절한 처리를 합니다.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace 异步调用实现方法汇总4 { /// <summary> /// 异步调用方法总结: /// 4.回调 /// 之前三种方法者在等待异步方法执行完毕后才能拿到执行的结果,期间主线程均处于等待状态。 /// 回调和它们最大的区别是,在调用BeginInvoke时只要提供了回调方法,那么主线程就不必要再等待异步线程工作完毕, /// 异步线程在工作结束后会主动调用我们提供的回调方法,并在回调方法中做相应的处理,例如显示异步调用的结果。 /// </summary> class Program { public delegate void PrintDelegate(string s); static void Main(string[] args) { PrintDelegate printDelegate = Print; Console.WriteLine("主线程."); printDelegate.BeginInvoke("Hello world.", PrintComeplete, printDelegate); Console.WriteLine("主线程继续执行..."); Console.WriteLine("Press any key to continue..."); Console.ReadKey(true); } public static void Print(string s) { Console.WriteLine("当前线程:"+s); Thread.Sleep(5000); } //回调方法要求 //1.返回类型为void //2.只有一个参数IAsyncResult public static void PrintComeplete(IAsyncResult result) { (result.AsyncState as PrintDelegate).EndInvoke(result); Console.WriteLine("当前线程结束." + result.AsyncState.ToString()); } } }
프로그램 실행 결과는 다음과 같습니다.
EndInvoke 메소드를 통해 동기화 함수의 반환 값을 가져옵니다. 위 동기화 방법의 반환 값은 void입니다.
using System.Diagnostics; using System.Threading; using System.Windows; namespace TestDelegateWrapper { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void ButtonBase_OnClick(object sender, RoutedEventArgs e) { WrapperSyncMethodAsync("ABC"); Trace.WriteLine("Main thread continue..."); } private delegate string SyncMethod1Delegate(string str); private void WrapperSyncMethodAsync(string str) { SyncMethod1Delegate syncMethod1Delegate = SyncMethod1; syncMethod1Delegate.BeginInvoke(str, x => { var result= syncMethod1Delegate.EndInvoke(x); // using the result to do something Trace.WriteLine(result); }, null); } private string SyncMethod1(string str) { Thread.Sleep(2000); return str; } } }
출력은 다음과 같습니다.
Main 스레드 계속...
ABC
위의 내용은 비동기 함수 호출을 구현하는 네 가지 방법으로 매우 명확합니다.