asp.net并行与多线程的理解[网站编程]
本文“asp.net并行与多线程的理解[网站编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
asp.net并行与多线程的理解
asp.net并发恳求数目影响的条件相当多,不考虑程序履行时间和能否被阻塞,它会遭到服务器tcp(普通windows服务器仿佛没限制)衔接数限制,iis衔接数限制,clr线程池对它的限制.
服务器tcp限制,[hklmsystemcurrentcontrolsetservicestcpipparameters] “enableconnectionratelimiting” =dword:00000000, 该注册表项的值改成 “0” 便可,假如是比方windows2003服务器,普通是没有这个限制的,比方我自己的2003没有.
iis衔接数限制:iis6及以下,%systemroot%system32inetsrv下的metabase.xml文件里直接改正,比方改正默许的asprequestqueuemax="3000",可以把恳求排行列队设置更大,改正默许的aspprocessorthreadmax="25",把request并发恳求线程设置更大等,具体可以参考相关资料,进程太多会设置到cpu切换线程要耗时,按照网上说法,并非越大越好,但可以综合按照并发量和系统性能相关形成设置;iis7配置的地方又不一样了,%systemroot%system32inetsrvconfigapplicationhost.config文件里改正,改正<serverruntime appconcurrentrequestlimit="5000" /> ,并发恳求限制数目,
iis manager > applicationpools > advanced settings, queue length:1000修转业列长度.hklmsystemcurrentcontrolsetserviceshttpparameters maxconnections 改正更大.
.net框架方面的限制
我认为一个asp.net程序运行起来后, 不关心差别的iis版本,它们生命逻辑不一样,iis6交给的进程之前也不一样,但我认为该进程都至少由三个线程池来管理,一个clr负责差别request恳求的工作线程池,一个io处理线程,还有该进程的非托管级的线程池,托管的这两个线程池的初始化和最大数目都可以配置和程序设置,非托管的线程池用于中转恳求给clr处理,和有io大概其他异步操作时,处理的非托管级线程.当然托管级的线程池我们是可以作一定掌握的,差别.net版本,和系统cpu数目,初始化线程池数目是不一样的,比方我目前cpu是单cpu双核系统,在.net4下一个mvc恳求中履行下面代码:
int workthread = 0;
int iothread = 0;
threadpool.getmaxthreads(out workthread, out iothread);
获得到最大工作线程池和io线程池都为200,但假如按照相关资料,说该值为100 *cpu数目(双核也算多个cpu),windows程序中获得到的值将更大,阐明默许系统给的线程数是不一样的.
在差别.net版本中,machine.config中<processmodel autoconfig="true"/>采取默许配置,我认为应当是.net差别版本里直接写死了默许线程数目等信息,可以通过改正machine.config中该节点的一些值来到达差别的目的,默许配置的一下参数:
设置maxworkerthreaders和maxiothreads为100
设置maxconnection 为12*cpu数目
设置minfreethreads为88*cpu数目
设置minworkerthreads为50
最大线程数目 = (最大工作线程 * cpu数目) - 最小闲暇线程, 当然还有其他一些重要的参数.
这些都是iis6和iis7经典情势下的配置文件的改正,ii7集成情势又有点不一样了,恳求最大数目由下面决意:maxconcurrentrequestspercpu:限制每个cpu履行的恳求的数目,即便有更多的线程可用.在.net 3.5及从前的版本中,默许值是12,在.net 4中是5000.假如设为0,没有限制;maxconcurrentthreadspercpu:限制每个cpu处理恳求的线程的数目.默许值是0,没有限制.这基本上就相当于对恳求数目没有限制了,同时 <processmodel
requestqueuelimit="10000"/> 加了
表示恳求列队行列10000,在%systemroot%system32inetsrvconfigapplicationhost.config中设置,<serverruntime appconcurrentrequestlimit="10000" /> ,都是增添并行恳求限制的
看一款多线程操作代码操纵socket
首先必须包含的两个命名空间:
using system.net;
using system.net.sockets;
几个常用的类:(这些东西,查下msdn就很具体了)
iphostentry, dns,ipaddress,ipendpoint,还有最重要的socket
ipendpoint: 这个是网络终结点,很好理解,就是网络上一个固定的地址:一个ip与一个端口的组合.
下面我还是以我从前写的一个很简单的聊天程序做示例吧, (很短代码的)
form1.cs
//阐明下, 这个是集server与client与一体的.
using system;
using system.collections.generic;
using system.componentmodel;
using system.data;
using system.drawing;
using system.text;
using system.windows.forms;
using system.net;
using system.net.sockets; //这个和上面的是利用socket必须的.
using system.io;
using system.threading; //这个是利用多线程必须的.namespace onlysocket
{
public partial class form1 : form //partial表示这块代码只是form1类的部份, form1类担当自form类
{
public form1()
{
initializecomponent(); //构造函数, 初始化容器.
}
socket sock; //定义一个socket类的对象 (默许为protected)
thread th; //定义一个thread类的对象
//public static ipaddress getserverip() //静态函数, 无需实例化便可调用.
{
iphostentry ieh = dns.gethostbyname(dns.gethostname()); //不多说了, dns类的两个静态函数//或用dns.resolve()替换gethostname()
return ieh.addresslist[0]; //返回address类的一个实例. 这里addresslist是数组并不奇特,一个server有n个ip都有大概
}
private void beginlisten() //socket监听函数, 等下作为成立新线程的参数
{
ipaddress serverip = getserverip(); //调用本类静态函数getserverip得到本机ipaddress.
ipendpoint iep = new ipendpoint(serverip, convert.toint32(tbport.text)); //本地终结点
sock = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp); //实例化内成员sock
byte[] bytemessage = new byte[100]; //存放消息的字节数组缓冲区, 注意数组表示办法,和c差别的.
this.lbiep.text = iep.tostring();
sock.bind(iep); //socket类的一个重要函数, 绑定一个ip,
while (true) //这里弄了个死循环来监听端口, 有人会问死循环了,那程序不卡住了, 注意这只是个类, 这里还没有main函数呢.
{
try
{
sock.listen(5); //好了,sock绑定了本地终结点便可以开始监听了,5表示最大衔接数为5
socket newsock = sock.accept(); //这里又有socket类的一个重要的办法:accept, 该办法承受来自表面的socket衔接恳求, 并返回一个socket套接字, 这个套接字就开始处理这一个client与server之间的对话
newsock.receive(bytemessage); //承受client发送过来的数据保存到缓冲区.
string msg = "from [" + newsock.remoteendpoint.tostring() + "]:" +system.text.encoding.utf8.getstring(bytemessage)+"n"; //getstring()函数将byte数组转换为string范例.
rtbtalk.appendtext(msg+"n"); //显示在文本控件里
}
catch (socketexception se) //捕捉非常,
{
lbstate.text = se.tostring(); //将其显示出来, 在此亦可以自定义错误.
}
}
}private void btconnect_click(object sender, eventargs e) //衔接按钮触发的事件: 衔接server
{
btconnect.enabled = false;
btstopconnect.enabled = true;
try
{
th = new thread(new threadstart(beginlisten)); //成立一个新的线程专门用于处理监听,这句话可以脱离写的,比方: threadstart ts=new threadstart(beginlisten); th=new thread (ts); 不过要注意, threadstart的构造函数的参数一定如果无参数的函数. 在此函数名其实就是其指针, 这里是拜托吗?
th.start(); //启动线程
lbstate.text = "listenning...";
}
catch (socketexception se) //处理非常
{
messagebox.show(se.message, "呈现问题", messageboxbuttons.ok, messageboxicon.information);
}
catch (argumentnullexception ae) //参数为空非常
{
lbstate.text = "参数错误";
messagebox.show(ae.message, "错误", messageboxbuttons.ok, messageboxicon.warning);
}}
private void btstopconnect_click(object sender, eventargs e) //终止监听
{
btstopconnect.enabled = false;
btconnect.enabled = true;
sock.close(); //关闭套接字
th.abort(); //终止监听线程
lbstate.text = "listenning stopped";
}private void btexit_click(object sender, eventargs e)
{
sock.close();
th.abort();
dispose(); //清理资源,就是释放内存
this.close(); //关闭对话框, 退出程序
}private void btsend_click(object sender, eventargs e)
{
try
{
ipaddress clientip = ipaddress.parse(tbtargetip.text); //类ipaddress的静态函数parse() :将text转化为ipaddress的一个实例.
int clientport = convert.toint32(tbport.text); //c#的这些转化函数很便利的,不像c++那样麻烦
ipendpoint clientiep = new ipendpoint(clientip, clientport); //这里用client表示不是很好....,
byte[] byte_message;
socket socket = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp); 实例化的时刻还有很多参数的, 这个是tcp的. tcp的sockettype是stream:数据流, 假如协议范例是udp, 则是数据包传送, qq就是用的udp.
socket.connect(clientiep); //socket的又一个函数connect(ipendpoint) .衔接远程套接字
byte_message = system.text.encoding.utf8.getbytes(rtbwords.text); //发现utf8可支持中文,就用之
socket.send(byte_message);
rtbtalk.appendtext("n"+"my words:" + rtbwords.text + "n");
socket.shutdown(socketshutdown.both);
socket.close();
}
catch (argumentnullexception ae)
{
messagebox.show(ae.message,"参数为空",messageboxbuttons.okcancel,messageboxicon.information);
}
catch (socketexception se)
{
messagebox.show(se.message, "呈现问题", messageboxbuttons.ok, messageboxicon.information);
}
}
}
}program.cs
using system;
using system.collections.generic;
using system.windows.forms;namespace onlysocket
{
static class program
{
/// <summary>
/// 利用程序的主进口点.
/// </summary>
[stathread]
static void main() //这儿才是main函数{
application.enablevisualstyles();
application.setcompatibletextrenderingdefault(false);
application.run(new form1());
}
}
}
写了半天了, 够累的了, 固然都是很底子的东西, 我自己写的时刻也复习了一边 , 呵呵.
其实多线程我自己也不是很纯熟, 记得去年暑假写过一个多线程扫描器, 也不知为啥, 线程开到50以上就非常, 很忧郁的. 其实当时我就是用的new thread=thread(new threadstart(fun))实现的, 办法感受很拙笨,呵呵.
大致代码仿佛是这样的吧:
先写个scan类:
public class scan
{
try{ public scan(){ ...init... }
public void scan{ ..task循环扫描... } //task构造体里面有ip, 端口, 能否已扫描标志flag}
catch{}
}
然后主函数里面可以这样搞:
scan[] scanner = new scan[xx]
thread[] thread = new thread[xx];
for (int i = 0; i < xx;i++)
{
scanner[i] = new scan(this, i);
thread[i] = new thread(new threadstart(scanner[i].startscan));
thread[i].start();}
其实这样便可以简单的实现多线程了.
以上是“asp.net并行与多线程的理解[网站编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |