c# 多线程

来源:互联网 发布:linux怎么查看网关 编辑:程序博客网 时间:2024/04/30 22:32
 
线程在C#中并不难实现。它有一个命名空System.Threading,提供了多线程的支持。
启一个新线程,需要以下的初始化:
ThreadStart startDownload = new ThreadStart( DownLoad ); //线程起始置:即线程都DownLoad(),注意:DownLoad()须为有参数的方法
Thread downloadThread = new Thread( startDownload ); //例化要启的新
downloadThread.Start();//线
 
由于线程起始的方法不能有参数,线程共享源添加了麻。不可以用类级变量(当然也可以使用其它方法,笔者认为此方法最简单易用)来解决问题。知道启多线程下的方法后,大家可能会生几个疑
1.       如何控制线程的数量?
2.       如何防止多线程下同一网
3.       如何判断线束?
4.       如何控制线束?
 
下面就几个问题提出解决方法:
1.       线程数量我可以通for实现,就如同当年初学程的打点程序一
比如已知用指定了n(它是一个int量)个线程吧,可以用如下方法启五个线
Thread[] downloadThread;//声名下载线程,C#优势,即数初始化,不需要指定其度,可以在使用才指定。个声名应为类级这样也就其它方法控件它提供了可能
ThreadStart startDownload = new ThreadStart( DownLoad );//线程起始置:即线程都DownLoad()
downloadThread = new Thread[ n ];//为线程申请资源,确定线
for( int i = 0; i < n; i++ )//启指定数量的线程数
{
    downloadThread[i] = new Thread( startDownload );//指定线程起始
    downloadThread[i].Start();//逐个线
}
好了,实现控制线程数是不是很简单啊?
2.       下面出的一个问题:所有的线程都DonwLoad()方法,这样如何避免它同一个网呢?
问题也好解决,只要建立一下Url地址表,表中的个地址只允被一个线程申即可。具体实现
可以利用数据,建立一个表,表中有四列,其中一列专门用于存Url地址,另外两列分存放地址对应线程以及地址被申的次数,最后一列存放下的内容。(当然,对应线程一列不是必要的)。当有线程申后,将对应线程一列当前线号,并将是否申请过一列一次,这样线程就无法申请该页。如果下成功,将内容存入内容列。如果不成功,内容列仍空,作是否再次下的依据之一,如果反不成功,则进程将于达到重次数(对应该地址被申的次数,用)后,申下一个Url地址。主要的代如下(以VFP例):
<建立表>
CREATE TABLE (ctablename) ( curl M , ctext M , ldowned I , threadNum I ) &&建立一个表ctablename.dbf,含有地址、文本内容、已经尝试次数、线志(初值为-1线志是从0始的整数)四个字段
<提取Url地址>
cfullname = (ctablename) + '.dbf'&&表添加展名
USE (cfullname) 
GO TOP
LOCATE FOR (EMPTY( ALLTRIM( ctext ) ) AND ldowned < 2 AND ( threadNum = thisNum OR threadNum = - 1) )  &&找尚未下成功且的属于本线限的Url地址,thisNum是当前线程的号,可以通参数传递得到
gotUrl = curl
recNum = RECNO()
IF recNum <= RECCOUNT() THEN  &&如果在列表中找到这样Url地址
UPDATE (cfullname) SET ldowned = ( ldowned + 1 ) , threadNum = thisNum WHERE RECNO() = recNum &&更新表,将此记录更新已申,即下次数加1线志列设为线程的号。
<内容>
cfulltablename = (ctablename) + '.dbf'
USE (cfulltablename)
SET EXACT ON
LOCATE FOR curl = (csiteurl) && csiteurl是参数,到的内容所对应Url地址
recNumNow = RECNO()&&得到含有此地址的记录
UPDATE (cfulltablename) SET ctext = (ccontent) WHERE RECNO() = recNumNow &&插入对应地址的对应内容
<插入新地址>
ctablename = (ctablename) + '.dbf'
USE (ctablename)
GO TOP
SET EXACT ON
LOCATE FOR curl = (cnewurl) &&找有无此地址
IF RECNO() > RECCOUNT() THEN &&如果尚无此地址
SET CARRY OFF
INSERT INTO (ctablename) ( curl , ctext , ldowned , threadNum ) VALUES ( (cnewurl) , "" , 0 , -1 )  &&将主地址添加到列表
好了,这样就解决了多线程中,线程冲突。当然,去重问题也可以在C#言内解决,只根建立一个临时文件(文本就可以),保存所有的Url地址,差们设置相的属性即可,但找效率可能不及数据快。
3.       线束是很判断的,因是在找新的接。用者认为可以假线程重N次以后是没有能申到新的Url地址,那可以认为它已完了所有接。主要代如下:
string url = "";
int times = 0;
while ( url == "" )//如果没有找到符合条件的记录不断地找符合条件的记录
{
    url = getUrl.GetAUrl( …… );//GetAUrl方法,试图得到一个url
    if ( url == "" )//如果没有找到
    {
       times ++;//尝试次数自增
       continue; //行下一次尝试
    }
    if ( times > N ) //如果已经尝试够了次数,退出
    {
       downloadThread[i].Abort; //退出
    }
    else//如果没有尝试够次数
    {
       Times = 0; //尝试次数
    }
    //行下一步针对得到的Url
}
4.       问题对简单,因问题一中已,将线程声名为类级这样就很易于控制。只要用一个for即可束。代如下:
for( int i = 0; i < n; i++ )//关闭指定数量n线程数
{
    downloadThread[i].Abort();//逐个关闭线
}