.net异步与多线程
http://blog.csdn.net/xiyou/archive/2006/09/19/1245614.aspx
上面地址看的更清楚。
一直不清楚异步与多线程的区别,不知道回调函数是在新线程还是原线程执行。
上网没查找到,自已研究。
using System;
using System.IO;
using System.Threading;
namespace test_异步
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
int i=0;
FileStream fs=new FileStream(@"c:kk.txt",FileMode.Create,FileAccess.Write,FileShare.Write);
fs.BeginWrite(new byte[]{1},0,1,new AsyncCallback(endWrite),fs);
while(true){
System.Console.WriteLine("main_"+i++);
Thread.Sleep(500);
}
}
public static void endWrite(IAsyncResult ir)
{
((FileStream)ir.AsyncState).Close();
int i=0;
while(true)
{
System.Console.WriteLine("endwrite_"+i++);
Thread.Sleep(100);
}
}
}
}
上面的结果是每输出5个 endwrite_i 输出一个 main_i ,说明异步也是在不同线程中运行,和多线程没什么不同。
但是MSDN和网上的代码上很多代码都是在回调函数中再次调用异步函数,这样岂不是会产生很多进程?不过MSDN中都这样写也许不是这样,再次测试。
using System;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;
namespace test_异步
{
class Class1
{
[DllImport("kernel32.dll")]
public static extern int GetCurrentThreadId();
[STAThread]
static void Main(string[] args)
{
int i=0;
FileStream fs=new FileStream(@"c:kk.txt",FileMode.Create,FileAccess.Write,FileShare.Write);
fs.BeginWrite(new byte[]{1},0,1,new AsyncCallback(endWrite),fs);
while(true){
System.Console.WriteLine("main_"+i++);
Thread.Sleep(100);
}
}
public static void endWrite(IAsyncResult ir)
{
Thread.Sleep(100);
((FileStream)ir.AsyncState).Close();
FileStream fs=new FileStream(@"c:kk.txt",FileMode.Create,FileAccess.Write,FileShare.Write);
fs.BeginWrite(new byte[]{1},0,1,new AsyncCallback(endWrite),fs);
System.Console.WriteLine("endwrite_"+GetCurrentThreadId());
}
}
}
输出结果:
main_0
main_1
endwrite_2264
main_2
endwrite_2264
main_3
endwrite_2264
main_4
endwrite_2264
main_5
endwrite_2356
main_6
endwrite_2356
main_7
endwrite_2356
main_8
endwrite_2356
main_9
endwrite_2264
endwrite_2356
endwrite_2264
可以看到产生线程的ID多是相同的,是使用了同一个线程还是线程结束后,新线程ID号相同?再次测试。
using System;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;
namespace test_异步
{
class Class1
{
[DllImport("kernel32.dll")]
public static extern int GetCurrentThreadId();
[STAThread]
static void Main(string[] args)
{
int i=0;
FileStream fs=new FileStream(@"c:kk.txt",FileMode.Create,FileAccess.Write,FileShare.Write);
fs.BeginWrite(new byte[]{1},0,1,new AsyncCallback(endWrite),fs);
while(i<100){
System.Console.WriteLine("main_"+i++);
Thread.Sleep(100);
}
}
public static void endWrite(IAsyncResult ir)
{
((FileStream)ir.AsyncState).Close();
FileStream fs=new FileStream(@"c:kk.txt",FileMode.Create,FileAccess.Write,FileShare.Write);
fs.BeginWrite(new byte[]{1},0,1,new AsyncCallback(endWrite),fs);
System.Console.WriteLine("endwrite_"+GetCurrentThreadId());
Thread.Sleep(100);
}
}
}
结果输出:
…………
main_98
endwrite_2204
endwrite_3884
endwrite_2280
endwrite_2216
endwrite_1632
endwrite_740
endwrite_3760
endwrite_4016
endwrite_1220
endwrite_1784
endwrite_4088
endwrite_3964
endwrite_2160
endwrite_2360
endwrite_2352
endwrite_912
endwrite_2376
endwrite_4048
endwrite_2364
endwrite_4076
endwrite_4008
endwrite_992
main_99
endwrite_2204
endwrite_3884
endwrite_2280
endwrite_2216
endwrite_1632
endwrite_740
endwrite_3760
endwrite_4016
endwrite_1220
endwrite_1784
endwrite_4088
endwrite_3964
endwrite_2160
endwrite_2360
endwrite_2352
endwrite_912
endwrite_2376
endwrite_4048
endwrite_2364
endwrite_4076
endwrite_4008
endwrite_992
看来MSDN没什么错,异步和多线程没什么区别,但我还是觉得递归调用异步函数不好,不够清晰。
问题点数:100、回复次数:10Top
1 楼VirtualDesktop(^_^)回复于 2006-09-19 18:27:03 得分 2
回调函数在新线程执行的Top
2 楼IceboundRock()回复于 2006-09-20 19:08:16 得分 20
异步有的时候用普通的线程,有的时候用系统的异步调用功能。
有一些IO操作也是异步的,但是未必需要一个线程来运行。例如:硬件是有DMA功能的,在调用DMA传输数据的时候,CPU是不需要执行处理的,只需要发起传输和等待传输结束即可。
具体到.net平台,比如Socket的BeginSend,如果是运行在Windows 2000以后的平台,在底层就会调用异步的完成端口来发送。
Top
3 楼bnflower()回复于 2006-09-21 09:49:40 得分 5
.Net中的异步执行其实使用的是异步委托。异步委托将要执行的方法提交到.net的线程池,由
线程池中的线程来执行异步方法。Top
4 楼xiyou(溪游at福州)回复于 2006-09-21 10:43:44 得分 0
谢谢上面兄弟的回答。
我在socket编程的时候,开始以为异步委托的回调函数在主线程运行。
后来觉得不对,于是有了上面的测试。
现在有些明白:与多线程比那些异步函数在内部有些优化。
还有些不明白的地方
MSDN中 ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.2052/cpguide/html/cpconnon-blockingclientsocketexample.htm
private static void ReceiveCallback( IAsyncResult ar ) {
StateObject state = (StateObject) ar.AsyncState;
Socket client = state.workSocket;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0) {
client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,new AsyncCallback(ReceiveCallback), state);
} else {
receiveDone.Set();
}
}
一直在递归调用异步函数,我觉得已经是另一线程了,用while()就可以,为什么要用递归,还频繁线程上进进出出?Top
5 楼IceboundRock()回复于 2006-09-22 23:51:56 得分 5
其实这个方法是想保证Receive数据的顺序。前一个接收完成之后再发起后一个接收。并不是递归。Top
6 楼www_123du_com(鼠·神·泪)回复于 2006-09-23 00:01:09 得分 25
异步执行也得执行,不在当前线程执行,当然得去另外一个线程执行。
异步通常用系统线程池的线程,通常情况下性能好些。(因为可以多次利用,申请时不需要重新申请一个线程,只需要从池里取就行了。)
异步是一种效果,多线程是一种具体技术。可以说,用“多线程”实现“异步”。Top
7 楼holerescue(人因理想而伟大)回复于 2006-09-23 23:34:04 得分 25
异步和多线程是两个不同的概念,不能这样比较。
异步请求一般用在IO等耗时操作上,他的好处是函数调用立即返回,相应的工作线程立即返还给系统以供重用。由于系统的线程资源是非常宝贵的,通常有一定的数目限制,如.net默认是25。若使用异步方式,用这些固定数目的线程在固定的时间内就可以服务更多的请求,而如果用同步方式,那么每个请求都自始至终占用这一个线程,服务器可以同时服务的请求数就少了。当异步操作执行完成后,系统会从可用线程中选取一个执行回调程序,这时的这个线程可能是刚开始发出请求的那个线程,也可能是其他的线程,因为系统选取线程是随机的事情,所以不能说绝对不是刚开始的那个线程。
多线程是用来并发的执行多个任务。想必楼主应该清楚这个概念。Top
8 楼bejon(阿牛[如果我懂,必坦诚相告;如果您懂,请不吝赐教。])回复于 2006-09-23 23:48:36 得分 10
楼主认为,异不只不过是优化的多线程,我挺认同的。
不过有个问题,异步有时优先级比主线程还高。这个特点和多线程不同。Top
9 楼libraworm(我要改名)回复于 2006-09-24 17:13:39 得分 8
异步跟多线程不算是一个概念吧。
异步是一中表现形式,多线程是一中实现手段。
另外,回调是否用多线程完全取决于你的调用方式,很简单的例子,Array的排序就是回调的IComparer的接口,但很明显排序不是多线程的。Top
10 楼xiyou(溪游at福州)回复于 2006-09-27 08:54:22 得分 0
多谢上面兄弟们的回答,虽然还是有些迷糊,不过已经足够我判断项目什么地方需要用异步。
这几天比较忙,没上。最后问一个问题,大家的这方面知识是从什么地方得到的,是从书上,MSDN上,国内网络,国外网络?我看过的书上没有说这方面的知识,MSDN,国内网络上也没有搜索到。
明天结贴。Top




