- 浏览: 123662 次
-
文章分类
最新评论
同步方法和异步方法的区别
同步方法和异步方法的区别
同步方法调用在程序继续执行之前需要等待同步方法执行完毕返回结果
异步方法则在被调用之后立即返回以便程序在被调用方法完成其任务的同时执行其它操作
林sir提示:在异步方法里面,注意的是回调函数!搞定了回调函数就基本了解异步编程。
异步编程的基础:http://www.cnblogs.com/ericwen/archive/2008/03/12/1101801.html
同步方法和异步方法的区别
同步方法调用在程序继续执行之前需要等待同步方法执行完毕返回结果
异步方法则在被调用之后立即返回以便程序在被调用方法完成其任务的同时执行其它操作
异步编程概览
.NETFramework允许您异步调用任何方法。定义与您需要调用的方法具有相同签名的委托;公共语言运行库将自动为该委托定义具有适当签名
的BeginInvoke和EndInvoke方法。
BeginInvoke方法用于启动异步调用。它与您需要异步执行的方法具有相同的参数,只不过还有两个额外的参数(将在稍后描述)。
BeginInvoke立即返回,不等待异步调用完成。
BeginInvoke返回IasyncResult,可用于监视调用进度。
EndInvoke方法用于检索异步调用结果。调用BeginInvoke后可随时调用EndInvoke方法;如果异步调用未完成,EndInvoke将一直阻塞到
异步调用完成。EndInvoke的参数包括您需要异步执行的方法的out和ref参数(在VisualBasic中为<Out>ByRef和ByRef)以及由
BeginInvoke返回的IAsyncResult。
四种使用BeginInvoke和EndInvoke进行异步调用的常用方法。调用了BeginInvoke后,可以:
1.进行某些操作,然后调用EndInvoke一直阻塞到调用完成。
2.使用IAsyncResult.AsyncWaitHandle获取WaitHandle,使用它的WaitOne方法将执行一直阻塞到发出WaitHandle信号,然后调用
EndInvoke。这里主要是主程序等待异步方法,等待异步方法的结果。
3.轮询由BeginInvoke返回的IAsyncResult,IAsyncResult.IsCompeted确定异步调用何时完成,然后调用EndInvoke。此处理个人认为与
相同。
4.将用于回调方法的委托传递给BeginInvoke。该方法在异步调用完成后在ThreadPool线程上执行,它可以调用EndInvoke。这是在强制装
换回调函数里面IAsyncResult.AsyncState(BeginInvoke方法的最后一个参数)成委托,然后用委托执行EndInvoke。
警告始终在异步调用完成后调用EndInvoke。
以上有不理解的稍后可以再理解。
例子
1)先来个简单的没有回调函数的异步方法例子
请再运行程序的时候,仔细看注释,对理解很有帮助。还有,若将注释的中的两个方法都同步,你会发现异步运行的速度优越性。
usingSystem;
namespaceConsoleApplication1
{
classClass1
{
//声明委托
publicdelegatevoidAsyncEventHandler();
//异步方法
voidEvent1()
{
Console.WriteLine("Event1Start");
System.Threading.Thread.Sleep(4000);
Console.WriteLine("Event1End");
}
//同步方法
voidEvent2()
{
Console.WriteLine("Event2Start");
inti=1;
while(i<1000)
{
i=i+1;
Console.WriteLine("Event2"+i.ToString());
}
Console.WriteLine("Event2End");
}
[STAThread]
staticvoidMain(string[]args)
{
longstart=0;
longend=0;
Class1c=newClass1();
Console.WriteLine("ready");
start=DateTime.Now.Ticks;
//实例委托
AsyncEventHandlerasy=newAsyncEventHandler(c.Event1);
//异步调用开始,没有回调函数和AsyncState,都为null
IAsyncResultia=asy.BeginInvoke(null,null);
//同步开始,
c.Event2();
//异步结束,若没有结束,一直阻塞到调用完成,在此返回该函数的return,若有返回值。
asy.EndInvoke(ia);
//都同步的情况。
//c.Event1();
//c.Event2();
end=DateTime.Now.Ticks;
Console.WriteLine("时间刻度差="+Convert.ToString(end-start));
Console.ReadLine();
}
}
}
2)下面看有回调函数的WebRequest和WebResponse的异步操作。
usingSystem;
usingSystem.Net;
usingSystem.Threading;
usingSystem.Text;
usingSystem.IO;
//RequestState类用于通过
//异步调用传递数据
publicclassRequestState
{
constintBUFFER_SIZE=1024;
publicStringBuilderRequestData;
publicbyte[]BufferRead;
publicHttpWebRequestRequest;
publicStreamResponseStream;
//创建适当编码类型的解码器
publicDecoderStreamDecode=Encoding.UTF8.GetDecoder();
publicRequestState()
{
BufferRead=newbyte[BUFFER_SIZE];
RequestData=newStringBuilder("");
Request=null;
ResponseStream=null;
}
}
//ClientGetAsync发出异步请求
classClientGetAsync
{
publicstaticManualResetEventallDone=newManualResetEvent(false);
constintBUFFER_SIZE=1024;
publicstaticvoidMain(string[]args)
{
if(args.Length<1)
{
showusage();
return;
}
//从命令行获取URI
UriHttpSite=newUri(args[0]);
//创建请求对象
HttpWebRequestwreq=(HttpWebRequest)WebRequest.Create(HttpSite);
//创建状态对象
RequestStaters=newRequestState();
//将请求添加到状态,以便它可以被来回传递
rs.Request=wreq;
//发出异步请求
IAsyncResultr=(IAsyncResult)wreq.BeginGetResponse(newAsyncCallback(RespCallback),rs);
//将ManualResetEvent设置为Wait,
//以便在调用回调前,应用程序不退出
allDone.WaitOne();
}
publicstaticvoidshowusage()
{
Console.WriteLine("尝试获取(GET)一个URL");
Console.WriteLine("\r\n用法::");
Console.WriteLine("ClientGetAsyncURL");
Console.WriteLine("示例::");
Console.WriteLine("ClientGetAsynchttp://www.microsoft.com/net/");
}
privatestaticvoidRespCallback(IAsyncResultar)
{
//从异步结果获取RequestState对象
RequestStaters=(RequestState)ar.AsyncState;
//从RequestState获取HttpWebRequest
HttpWebRequestreq=rs.Request;
//调用EndGetResponse生成HttpWebResponse对象
//该对象来自上面发出的请求
HttpWebResponseresp=(HttpWebResponse)req.EndGetResponse(ar);
//既然我们拥有了响应,就该从
//响应流开始读取数据了
StreamResponseStream=resp.GetResponseStream();
//该读取操作也使用异步完成,所以我们
//将要以RequestState存储流
rs.ResponseStream=ResponseStream;
//请注意,rs.BufferRead被传入到BeginRead。
//这是数据将被读入的位置。
IAsyncResultiarRead=ResponseStream.BeginRead(rs.BufferRead,0,BUFFER_SIZE,newAsyncCallback(ReadCallBack),rs);
}
privatestaticvoidReadCallBack(IAsyncResultasyncResult)
{
//从asyncresult获取RequestState对象
RequestStaters=(RequestState)asyncResult.AsyncState;
//取出在RespCallback中设置的ResponseStream
StreamresponseStream=rs.ResponseStream;
//此时rs.BufferRead中应该有一些数据。
//读取操作将告诉我们那里是否有数据
intread=responseStream.EndRead(asyncResult);
if(read>0)
{
//准备Char数组缓冲区,用于向Unicode转换
Char[]charBuffer=newChar[BUFFER_SIZE];
//将字节流转换为Char数组,然后转换为字符串
//len显示多少字符被转换为Unicode
intlen=rs.StreamDecode.GetChars(rs.BufferRead,0,read,charBuffer,0);
Stringstr=newString(charBuffer,0,len);
//将最近读取的数据追加到RequestDatastringbuilder对象中,
//该对象包含在RequestState中
rs.RequestData.Append(str);
//现在发出另一个异步调用,读取更多的数据
//请注意,将不断调用此过程,直到
//responseStream.EndRead返回-1
IAsyncResultar=responseStream.BeginRead(rs.BufferRead,0,BUFFER_SIZE,newAsyncCallback(ReadCallBack),rs);
}
else
{
if(rs.RequestData.Length>1)
{
//所有数据都已被读取,因此将其显示到控制台
stringstrContent;
strContent=rs.RequestData.ToString();
Console.WriteLine(strContent);
}
//关闭响应流
responseStream.Close();
//设置ManualResetEvent,以便主线程可以退出
allDone.Set();
}
return;
}
}
在这里有回调函数,且异步回调中又有异步操作。
首先是异步获得ResponseStream,然后异步读取数据。
这个程序非常经典。从中可以学到很多东西的。我们来共同探讨。
总结
上面说过,.netframework可以异步调用任何方法。所以异步用处广泛。
在.netframework类库中也有很多异步调用的方法。一般都是已Begin开头End结尾构成一对,异步委托方法,外加两个回调函数和AsyncState参数,组成异步操作的宏观体现。所以要做异步编程,不要忘了委托delegate、Begin,End,AsyncCallBack委托,AsyncState实例(在回调函数中通过IAsyncResult.AsyncState来强制转换),IAsycResult(监控异步),就足以理解异步真谛了。
C#异步调用四大方法详解:
http://developer.51cto.com/art/200908/145541.htm
C#异步调用四大方法是什么呢?他们各自的作用是什么呢?那么本文就向你介绍C#异步调用四大方法的具体内容。
C#异步调用四大方法是什么呢?C#异步调用四大方法的使用是如何进行的呢?让我们首先了解下什么时候用到C#异步调用:
.NETFramework允许您C#异步调用任何方法。定义与您需要调用的方法具有相同签名的委托;公共语言运行库将自动为该委托定义具有适当签名的BeginInvoke和EndInvoke方法。
BeginInvoke方法用于启动C#异步调用。它与您需要异步执行的方法具有相同的参数,只不过还有两个额外的参数(将在稍后描述)。BeginInvoke立即返回,不等待C#异步调用完成。BeginInvoke返回IasyncResult,可用于监视调用进度。
EndInvoke方法用于检索C#异步调用结果。调用BeginInvoke后可随时调用EndInvoke方法;如果C#异步调用未完成,EndInvoke将一直阻塞到C#异步调用完成。EndInvoke的参数包括您需要异步执行的方法的out和ref参数(在VisualBasic中为ByRef和ByRef)以及由BeginInvoke返回的IAsyncResult。
注意VisualStudio.NET中的智能感知功能会显示BeginInvoke和EndInvoke的参数。如果您没有使用VisualStudio或类似的工具,或者您使用的是C#和VisualStudio.NET,请参见异步方法签名获取有关运行库为这些方法定义的参数的描述。
本主题中的代码演示了四种使用BeginInvoke和EndInvoke进行C#异步调用的常用方法。调用了BeginInvoke后,可以:
·进行某些操作,然后调用EndInvoke一直阻塞到调用完成。
·使用IAsyncResult.AsyncWaitHandle获取WaitHandle,使用它的WaitOne方法将执行一直阻塞到发出WaitHandle信号,然后调用EndInvoke。
·轮询由BeginInvoke返回的IAsyncResult,确定C#异步调用何时完成,然后调用EndInvoke。
·将用于回调方法的委托传递给BeginInvoke。该方法在C#异步调用完成后在ThreadPool线程上执行,它可以调用EndInvoke。
警告:始终在C#异步调用完成后调用EndInvoke。
测试方法和异步委托
四个示例全部使用同一个长期运行的测试方法TestMethod。该方法显示一个表明它已开始处理的控制台信息,休眠几秒钟,然后结束。TestMethod有一个out参数(在VisualBasic中为ByRef),它演示了如何将这些参数添加到BeginInvoke和EndInvoke的签名中。您可以用类似的方式处理ref参数(在VisualBasic中为ByRef)。
下面的代码示例显示TestMethod以及代表TestMethod的委托;若要使用任一示例,请将示例代码追加到这段代码中。
注意为了简化这些示例,TestMethod在独立于Main()的类中声明。或者,TestMethod可以是包含Main()的同一类中的static方法(在VisualBasic中为Shared)。
1usingSystem;
2usingSystem.Threading;
3
4publicclassAsyncDemo{
5//Themethodtobeexecutedasynchronously.
6//
7publicstringTestMethod(
8intcallDuration,outintthreadId){
9Console.WriteLine("Testmethodbegins.");
10Thread.Sleep(callDuration);
11threadId=AppDomain.GetCurrentThreadId();
12return"MyCallTimewas"+callDuration.ToString();
13}
14}
15
16//Thedelegatemusthavethesamesignatureasthemethod
17//youwanttocallasynchronously.
18publicdelegatestringAsyncDelegate(
19intcallDuration,outintthreadId);
20
21
22usingSystem;
23usingSystem.Threading;
24
25publicclassAsyncDemo{
26//Themethodtobeexecutedasynchronously.
27//
28publicstringTestMethod(
29intcallDuration,outintthreadId){
30Console.WriteLine("Testmethodbegins.");
31Thread.Sleep(callDuration);
32threadId=AppDomain.GetCurrentThreadId();
33return"MyCallTimewas"+callDuration.ToString();
34}
35}
36
37//Thedelegatemusthavethesamesignatureasthemethod
38//youwanttocallasynchronously.
39publicdelegatestringAsyncDelegate(
40intcallDuration,outintthreadId);
C#异步调用四大方法之使用EndInvoke等待异步调用
异步执行方法的最简单方式是以BeginInvoke开始,对主线程执行一些操作,然后调用EndInvoke。EndInvoke直到C#异步调用完成后才返回。这种技术非常适合文件或网络操作,但是由于它阻塞EndInvoke,所以不要从用户界面的服务线程中使用它。
41publicclassAsyncMain{
42staticvoidMain(string[]args){
43//Theasynchronousmethodputsthethreadidhere.
44intthreadId;
45
46//Createaninstanceofthetestclass.
47AsyncDemoad=newAsyncDemo();
48
49//Createthedelegate.
50AsyncDelegatedlgt=newAsyncDelegate(ad.TestMethod);
51
52//Initiatetheasychronouscall.
53IAsyncResultar=dlgt.BeginInvoke(3000,
54outthreadId,null,null);
55
56Thread.Sleep(0);
57Console.WriteLine("Mainthread{0}doessomework.",
58AppDomain.GetCurrentThreadId());
59
60//CallEndInvoketoWaitfor
61//theasynchronouscalltocomplete,
62//andtoretrievetheresults.
63stringret=dlgt.EndInvoke(outthreadId,ar);
64
65Console.WriteLine("Thecallexecutedonthread{0},
66withreturnvalue\"{1}\".",threadId,ret);
67}
68}
C#异步调用四大方法之使用WaitHandle等待异步调用
等待WaitHandle是一项常用的线程同步技术。您可以使用由BeginInvoke返回的IAsyncResult的AsyncWaitHandle属性来获取WaitHandle。C#异步调用完成时会发出WaitHandle信号,而您可以通过调用它的WaitOne等待它。
如果您使用WaitHandle,则在C#异步调用完成之后,但在通过调用EndInvoke检索结果之前,可以执行其他处理。
69publicclassAsyncMain{
70staticvoidMain(string[]args){
71//Theasynchronousmethodputsthethreadidhere.
72intthreadId;
73
74//Createaninstanceofthetestclass.
75AsyncDemoad=newAsyncDemo();
76
77//Createthedelegate.
78AsyncDelegatedlgt=newAsyncDelegate(ad.TestMethod);
79
80//Initiatetheasychronouscall.
81IAsyncResultar=dlgt.BeginInvoke(3000,
82outthreadId,null,null);
83
84Thread.Sleep(0);
85Console.WriteLine("Mainthread{0}doessomework.",
86AppDomain.GetCurrentThreadId());
87
88//WaitfortheWaitHandletobecomesignaled.
89ar.AsyncWaitHandle.WaitOne();
90
91//Performadditionalprocessinghere.
92//CallEndInvoketoretrievetheresults.
93stringret=dlgt.EndInvoke(outthreadId,ar);
94
95Console.WriteLine("Thecallexecutedonthread{0},
96withreturnvalue\"{1}\".",threadId,ret);
97}
98}
C#异步调用四大方法之轮询异步调用完成
您可以使用由BeginInvoke返回的IAsyncResult的IsCompleted属性来发现C#异步调用何时完成。从用户界面的服务线程中进行C#异步调用时可以执行此操作。轮询完成允许用户界面线程继续处理用户输入。
99publicclassAsyncMain{
100staticvoidMain(string[]args){
101//Theasynchronousmethodputsthethreadidhere.
102intthreadId;
103
104//Createaninstanceofthetestclass.
105AsyncDemoad=newAsyncDemo();
106
107//Createthedelegate.
108AsyncDelegatedlgt=newAsyncDelegate(ad.TestMethod);
109
110//Initiatetheasychronouscall.
111IAsyncResultar=dlgt.BeginInvoke(3000,
112outthreadId,null,null);
113
114//Pollwhilesimulatingwork.
115while(ar.IsCompleted==false){
116Thread.Sleep(10);
117}
118
119//CallEndInvoketoretrievetheresults.
120stringret=dlgt.EndInvoke(outthreadId,ar);
121
122Console.WriteLine("Thecallexecutedonthread{0},
123withreturnvalue\"{1}\".",threadId,ret);
124}
125}
C#异步调用四大方法之异步调用完成时执行回调方法
如果启动异步调用的线程不需要处理调用结果,则可以在调用完成时执行回调方法。回调方法在ThreadPool线程上执行。
要使用回调方法,必须将代表该方法的AsyncCallback委托传递给BeginInvoke。也可以传递包含回调方法将要使用的信息的对象。例如,可以传递启动调用时曾使用的委托,以便回调方法能够调用EndInvoke。
126publicclassAsyncMain{
127//Asynchronousmethodputsthethreadidhere.
128privatestaticintthreadId;
129
130staticvoidMain(string[]args){
131//Createaninstanceofthetestclass.
132AsyncDemoad=newAsyncDemo();
133
134//Createthedelegate.
135AsyncDelegatedlgt=newAsyncDelegate(ad.TestMethod);
136
137//Initiatetheasychronouscall.IncludeanAsyncCallback
138//delegaterepresentingthecallbackmethod,andthedata
139//neededtocallEndInvoke.
140IAsyncResultar=dlgt.BeginInvoke(3000,
141outthreadId,
142newAsyncCallback(CallbackMethod),
143dlgt);
144
145Console.WriteLine("PressEntertocloseapplication.");
146Console.ReadLine();
147}
148
149//Callbackmethodmusthavethesamesignatureasthe
150//AsyncCallbackdelegate.
151staticvoidCallbackMethod(IAsyncResultar){
152//Retrievethedelegate.
153AsyncDelegatedlgt=(AsyncDelegate)ar.AsyncState;
154
155//CallEndInvoketoretrievetheresults.
156stringret=dlgt.EndInvoke(outthreadId,ar);
157
158Console.WriteLine("Thecallexecutedonthread{0},
159withreturnvalue\"{1}\".",threadId,ret);
160}
161}
C#异步调用四大方法的基本内容就向你介绍到这里,希望对你了解和学习C#异步调用有所帮助。
相关推荐
在编程领域,同步和异步方法是处理任务执行方式的两种基本模式,它们在系统设计和性能优化中扮演着至关重要的角色。理解这两者的区别及其优缺点对于开发高效的应用至关重要。 **同步方法**指的是调用一个函数或方法...
Node.js中让异步操作变成同步的方法通常是指将非阻塞的异步调用改写为在逻辑上表现得像同步调用的方式。Node.js中异步操作是通过回调函数、Promises和async/await等技术来实现的。以下我们详细讲解如何通过这些方法...
Angular异步变同步处理方法是前端开发中用于解决多个接口请求顺序依赖问题的一种技术手段。由于异步操作的特性,它能处理那些按顺序依次执行的接口调用,而不会阻塞主线程,让页面陷入假死状态。在Angular中,主要...
通过74LS161功能表的阅读和理解,以及反馈清零法和反馈置数法的应用,我们可以更深入地掌握异步清零和同步清零置数的区别及其应用。 总结来说,异步清零与同步清零的区别在于是否依赖于时钟信号的上升沿或下降沿来...
Java中将异步调用转换为同步调用有多种方法,本文将详细介绍五种方法:使用wait和notify方法、使用条件锁、使用Future、使用CountDownLatch、使用CyclicBarrier。 1. 使用wait和notify方法 wait和notify方法是...
例如,可能存在一个Server类用于启动监听,一个Client类用于建立连接,它们都有同步和异步版本的发送和接收数据的方法。 在实际应用中,同步通信适用于简单、低并发的场景,而异步通信适合高并发和实时性要求较高的...
这种方法通过添加“复位同步器”(Reset Synchronizer)模块,将异步复位信号转换为与特定时钟同步的信号,确保复位信号释放时的稳定性和可预测性。 Verilog代码示例: ```verilog module Reset_Synchronizer ...
本文档详细描述了同步电路的概念和异步电路的概念以及两者之间的区别。
PROE 二次开发同步异步两种模式的区别 PROE 二次开发中,同步模式和异步模式是两种不同的开发方式。同步模式(Synchronous Mode)是指 PRO/Toolkit 应用程序进程和 PRO/ENGINEER 系统进程不能同时操作,需要等待...
同步通信和异步通信是两种基本的通信方式,它们在数据传输中有着不同的特点和应用场景。下面我们将详细探讨这两种通信模式的区别。 首先,异步通信,又称为起止式通信,其主要特点是允许字符间的时间间隔是任意的。...
- 异步环闭合差的计算方法与同步环类似,但需要考虑更多的外部因素。 #### 四、闭合差计算意义及应用 - **意义**:闭合差计算能够帮助我们评估GPS控制网的整体质量。通过对同步环和异步环闭合差的计算,可以有效...
在编程领域,同步执行与异步执行是两种不同的任务处理方式,它们关乎程序的执行效率和用户体验。同步执行和异步执行是理解并发编程和多线程编程的关键概念。 **同步执行** 是一种线性、顺序的执行模式。在同步执行...
同步复位和异步复位是两种常见的复位类型,它们各有特点,适用于不同的应用场景。以下是对这两种复位方式的详细比较: ### 1. 同步复位(Synchronous Reset) **定义**:同步复位是一种与系统时钟同步的复位方式,...
在编程领域,尤其是在高性能和高并发的场景下,理解和掌握同步与异步读写是非常关键的。C#作为微软开发的面向对象的编程语言,提供了丰富的API和特性来支持这两种操作模式。本篇文章将深入探讨C#中的同步与异步读写...
本文将深入探讨几种异步时钟域同步化处理的方法,以确保系统稳定性和可靠性。 首先,我们来理解一下什么是异步时钟域。在FPGA设计中,不同的模块或功能块可能由不同的时钟源驱动,这些时钟源的频率可能相同也可能...
本文讲述了JS同步、异步、延迟加载的方法。分享给大家供大家参考,具体如下: 一:同步加载 我们平时使用的最多的一种方式。 [removed][removed] 同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止后续的解析...
Verilog 中的同步复位、...* 异步复位和同步复位的定义和区别 * 异步复位的优缺点 * 同步复位的优缺点 * 同步释放机制的实现 * PLL 配置复位设计的应用场景 * FPGA 设计中的复位机制 * Verilog 语言中的复位机制实现
这就是同步传输和异步传输的区别,也是同步串口和异步串口的区别。 同步串口和异步串口都是 RS232C 方式的体现,主要区别是在它们的传输方式上。异步传输是指一次传输一个字符(5~8 位)的数据。每个字符用一个韦始...
电动机按结构及工作原理分类电动机按结构及工作原理可分为直流电动机,异步电动机和同步电动机。同步电动机还可分为永磁同步电动