实验五线程和异步编程训练.docx
《实验五线程和异步编程训练.docx》由会员分享,可在线阅读,更多相关《实验五线程和异步编程训练.docx(16页珍藏版)》请在冰点文库上搜索。
实验五线程和异步编程训练
【1】能力培养要求:
熟悉多线程编程技术
【2】实验内容、目的、要求:
了解线程的概念,能用多线程编程技术编写程序。
【3】实验步骤:
本实验中所包含的以下项目均存放在名称为Lab5的解决方案中,该解决方案存放在D盘上。
1、委托训练
1)创建控制台项目ConsoleApplication,在Program.cs中编写代码(参见P166),并在“Hello”方法中添加语句:
Console.WriteLine("Hello:
"+s);在“AMethod”方法中添加语句:
Console.WriteLine("AMethod:
"+s);在Main中编写程序,完成如下功能:
创建委托的两个实例,分别委托到类MyClass中两个方法,并执行委托,传递的参数均为“world”。
试分析Main的运行结果。
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceConsoleApplication
{
delegatevoidMyDelegatel(strings);
publicclassMyClass
publicstaticvoidHello(strings)
"+s);
}
publicvoidAMethod(strings)
classProgram
staticvoidMain(string[]args)
MyDelegatela=newMyDelegatel(MyClass.Hello);
a("World");
MyClassp=newMyClass();
MyDelegatelb=newMyDelegatel(p.AMethod);
b("World");
Console.ReadLine();
2)创建控制台项目MultiApplication,在Program.cs中编写代码(参见P168--169),进行多路广播委托的练习,观察程序的输出结果。
说明多路广播委托的执行过程,并说明Invoke、GetInvocationList、Target和Method的作用。
namespaceMultiApplication
publicdelegatevoidMyDelegate2();
publicclassFoo
publicvoidBar()
Console.WriteLine("Barinvoked");
classApplication{
FooaFoo1=newFoo();
FooaFoo2=newFoo();
MyDelegate2a,b,c,d;
a=newMyDelegate2(aFoo1.Bar);
b=newMyDelegate2(aFoo2.Bar);
c=(MyDelegate2)Delegate.Combine(a,b);
d=(MyDelegate2)Delegate.Remove(c,a);
Delegate[]DelegateList=c.GetInvocationList();
for(inti=0;i{if(DelegateList[i].Target!=aFoo1){((MyDelegate2)DelegateList[i])();}}}}}2、线程训练1)创建控制台项目ThreadApplication,在Program.cs中编写代码(参见P171--172),进行线程的练习。在“AStaticMethod”方法中添加语句:Console.WriteLine("执行了静态方法AStaticMethod");在“AnInstanceMethod”方法中添加语句:Console.WriteLine("执行了实例方法AnInstanceMethod"),观察程序的输出结果。说明如何创建和启动新线程?usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading;namespaceThreadApplication{classMyClass{publicstaticvoidAStaticMethod(){Console.WriteLine("执行了静态方法AStaticMethod");}publicvoidAnInstanceMethod(){Console.WriteLine("执行了实例方法AnInstanceMethod");}}classApp{staticvoidMain(string[]args){MyClassaMyClass=newMyClass();Threadt1=newThread(newThreadStart(aMyClass.AnInstanceMethod));t1.Start();Threadt2=newThread(newThreadStart(MyClass.AStaticMethod));t2.Start();}}}2)创建控制台项目ThreadAttribute,在Program.cs中编写代码,对线程的名字、ID、优先级等属性进行测试,试分析代码的运行效果。代码如下:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading;namespaceThreadAttribute{classProgram{staticvoidMain(string[]args){Console.WriteLine("主程序线程在运行:");Threadcurrent_thread=Thread.CurrentThread;current_thread.Name="main";stringmain_p=current_thread.Priority.ToString();intmain_Id=current_thread.ManagedThreadId;Console.WriteLine("主程序的线程:");Console.WriteLine("名字:"+current_thread.Name);Console.WriteLine("优先级:"+main_p);Console.WriteLine("ID:"+main_Id);ThreadfThread=newThread(newThreadStart(First_Thread));fThread.Name="first_thread";fThread.Start();Console.WriteLine("主程序线程终止!");Console.ReadLine();}publicstaticvoidFirst_Thread(){Console.WriteLine("创建的线程在运行:");Threadcurrent_thread=Thread.CurrentThread;stringmain_p=current_thread.Priority.ToString();intmain_Id=current_thread.ManagedThreadId;Console.WriteLine("创建的线程:");Console.WriteLine("名字:"+current_thread.Name);Console.WriteLine("优先级:"+main_p);Console.WriteLine("ID:"+main_Id);Console.WriteLine("创建的线程终止!");}}} 3)定时器练习Thread.Timer类提供了一种在指定的时间间隔执行方法的机制。用TimerCallback委托指定与Timer相关联的方法。创建计时器时,指定第一次调用委托方法前的等待时间、后续调用之间的等待时间、计时器到截止时间时调用的方法。试编程演示计时器的用法。创建控制台项目TimerLx,在Program.cs中编写代码可参考P194。usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading;namespaceTimerLx{classApp{publicstaticvoidMain(){Console.WriteLine("Checkingforstatusupdatesevery2seconds.");Console.WriteLine("(HitEntertoterminatethesameple)");Timertimer=newTimer(newTimerCallback(CheckStatus),null,0,2000);Console.ReadLine();timer.Dispose();}staticvoidCheckStatus(Objectstate){Console.WriteLine("CheckingStatus.");}}}4)线程池练习线程池是.NETFramework中对线程的一种管理方式,由它来管理线程的生成和终止,而无须用户的干涉。要使用线程池,可调用ThreadPool.QueueUserWorkItem,传递一个WaitCallback委托,在其中包装要添加到队列中的方法。试编程演示线程池的用法。创建控制台项目PoolLx,在Program.cs中编写代码可参考P195--197。在P196的Read和Increment方法中添加代码:Console.WriteLine(threadNum.ToString());。请多次运行程序,注意观察线程的执行次序。usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading;namespacePoolLx{classCounter{publicvoidRead(intthreadNum){Console.WriteLine(threadNum.ToString());}publicvoidIncrement(intthreadNum){Console.WriteLine(threadNum.ToString());}}classApp{staticCountercounter=null;staticinttotalNumberofAsyncops=10;staticintnumAsyncops=totalNumberofAsyncops;staticAutoResetEventasyncopsAreDone=newAutoResetEvent(false);staticvoidMain(string[]args){counter=newCounter();for(intthreadNum=0;threadNumthreadNum++){ThreadPool.QueueUserWorkItem(newWaitCallback(UpdateResource),threadNum);}asyncopsAreDone.WaitOne();}staticvoidUpdateResource(objectstate){intthreadNum=(int)state;if((threadNum%2)!=0)counter.Read(threadNum);elsecounter.Increment(threadNum);if((Interlocked.Decrement(refnumAsyncops))==0)asyncopsAreDone.Set();}}} 5)多线程与Windows窗体控件Windows窗体控件只能在创建它们的线程上执行。如果要从后台线程获取或设置某个控件的属性,或调用该控件的方法,则必须把调用封送到创建该控件的线程。试以进度条控件ProgressBar为例进行编程。创建windows项目ProgressLx,代码可参考P198--199。请运行程序,注意观察效果。usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Windows.Forms;usingSystem.Threading; namespaceProgressLx{publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}ThreadtimerThread;privatevoidForm1_Load(objectsender,EventArgse){timerThread=newThread(newThreadStart(ThreadProc));timerThread.IsBackground=true;timerThread.Start();}publicvoidThreadProc(){try{MethodInvokermi=newMethodInvoker(this.UpdateProgress);while(true){this.BeginInvoke(mi);Thread.Sleep(500);}}catch(ThreadInterruptedExceptione){}catch(Exceptionwe){}}privatevoidUpdateProgress(){if(progressBar1.Value==progressBar1.Maximum){progressBar1.Value=progressBar1.Maximum;}progressBar1.PerformStep();}publicvoidDispose(){if(timerThread!=null){timerThread.Interrupt();timerThread=null;}}privatevoidprogressBar1_Click_1(objectsender,EventArgse){}}} 3、异步编程训练1)使用回调的方式实现文件的异步读取。代码可参考P203—204创建控制台项目CallbackReadFile,在Program.cs中编写代码。usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.IO;namespaceCallbackReadFile{classProgram{classMyState{publicstringfilename;publicMyState(stringfilename){this.filename=filename;}}staticbyte[]buffer=newbyte[2048];staticstringfilename="MyFile.txt";staticStreamaStream;staticMyStatemyState=newMyState(filename);staticvoidMain(string[]args){aStream=File.OpenRead(myState.filename);AsyncCallbackmyCallback=newAsyncCallback(OnReadDone);IAsyncResultar=aStream.BeginRead(buffer,0,buffer.Length,myCallback,(object)myState);Console.ReadLine();}staticvoidOnReadDone(IAsyncResultar){intbyteCount=aStream.EndRead(ar);Console.WriteLine("Filenameread:{0}",((MyState)(ar.AsyncState)).filename);aStream.Close();EncodingencodingGB2312=Encoding.GetEncoding("GB2312");Console.WriteLine(encodingGB2312.GetString(buffer));}}}2)使用轮询的方式实现文件的异步读取。代码可参考P203—204创建控制台项目PollingReadFile,在Program.cs中编写代码。usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.IO;namespacePollingReadFile{classProgram{classMyState{publicstringfilename;publicMyState(stringfilename){this.filename=filename;}}staticbyte[]buffer=newbyte[2048];staticstringfilename="MyFile.txt";staticStreamaStream;staticMyStatemyState=newMyState(filename);staticvoidMain(string[]args){aStream=File.OpenRead(myState.filename);IAsyncResultar=aStream.BeginRead(buffer,0,buffer.Length,null,(object)myState);while(!ar.IsCompleted){}intbyteCount=aStream.EndRead(ar);Console.WriteLine("Filenameread:{0}",((MyState)(ar.AsyncState)).filename);aStream.Close();EncodingencodingGB2312=Encoding.GetEncoding("GB2312");Console.WriteLine(encodingGB2312.GetString(buffer));}}}3)试说明代码中出现的AsyncCallback、BeginRead、EndRead、IasyncResult、AsyncState的含义。 【4】思考题1、publicdelegatevoidMyDelegate1(strings);该语句是一条委托声明,说明其含义?2、如何在.NETFramework中启动线程、管理线程和终止线程?3、获取异步操作的结果有哪些方法?
if(DelegateList[i].Target!
=aFoo1)
((MyDelegate2)DelegateList[i])();
2、线程训练
1)创建控制台项目ThreadApplication,在Program.cs中编写代码(参见P171--172),进行线程的练习。
在“AStaticMethod”方法中添加语句:
Console.WriteLine("执行了静态方法AStaticMethod");在“AnInstanceMethod”方法中添加语句:
Console.WriteLine("执行了实例方法AnInstanceMethod"),观察程序的输出结果。
说明如何创建和启动新线程?
usingSystem.Threading;
namespaceThreadApplication
classMyClass
publicstaticvoidAStaticMethod()
Console.WriteLine("执行了静态方法AStaticMethod");
publicvoidAnInstanceMethod()
Console.WriteLine("执行了实例方法AnInstanceMethod");
classApp
MyClassaMyClass=newMyClass();
Threadt1=new
Thread(newThreadStart(aMyClass.AnInstanceMethod));
t1.Start();
Threadt2=new
Thread(newThreadStart(MyClass.AStaticMethod));
t2.Start();
2)创建控制台项目ThreadAttribute,在Program.cs中编写代码,对线程的名字、ID、优先级等属性进行测试,试分析代码的运行效果。
代码如下:
namespaceThreadAttribute
Console.WriteLine("主程序线程在运行:
");
Threadcurrent_thread=Thread.CurrentThread;
current_thread.Name="main";
stringmain_p=current_thread.Priority.ToString();
intmain_Id=current_thread.ManagedThreadId;
Console.WriteLine("主程序的线程:
Console.WriteLine("名字:
"+current_thread.Name);
Console.WriteLine("优先级:
"+main_p);
Console.WriteLine("ID:
"+main_Id);
ThreadfThread=newThread(newThreadStart(First_Thread));
fThread.Name="first_thread";
fThread.Start();
Console.WriteLine("主程序线程终止!
publicstaticvoidFirst_Thread()
Console.WriteLine("创建的线程在运行:
Console.WriteLine("创建的线程:
Console.WriteLine("创建的线程终止!
3)定时器练习
Thread.Timer类提供了一种在指定的时间间隔执行方法的机制。
用TimerCallback委托指定与Timer相关联的方法。
创建计时器时,指定第一次调用委托方法前的等待时间、后续调用之间的等待时间、计时器到截止时间时调用的方法。
试编程演示计时器的用法。
创建控制台项目TimerLx,在Program.cs中编写代码可参考P194。
namespaceTimerLx
publicstaticvoidMain()
Console.WriteLine("Checkingforstatusupdatesevery2seconds.");
Console.WriteLine("(HitEntertoterminatethesameple)");
Timertimer=newTimer(newTimerCallback(CheckStatus),null,0,2000);
timer.Dispose();
staticvoidCheckStatus(Objectstate)
Console.WriteLine("CheckingStatus.");
4)线程池练习
线程池是.NETFramework中对线程的一种管理方式,由它来管理线程的生成和终止,而无须用户的干涉。
要使用线程池,可调用ThreadPool.QueueUserWorkItem,传递一个WaitCallback委托,在其中包装要添加到队列中的方法。
试编程演示线程池的用法。
创建控制台项目PoolLx,在Program.cs中编写代码可参考P195--197。
在P196的Read和Increment方法中添加代码:
Console.WriteLine(threadNum.ToString());。
请多次运行程序,注意观察线程的执行次序。
namespacePoolLx
classCounter
publicvoidRead(intthreadNum)
Console.WriteLine(threadNum.ToString());
publicvoidIncrement(intthreadNum)
staticCountercounter=null;
staticinttotalNumberofAsyncops=10;
staticintnumAsyncops=totalNumberofAsyncops;
staticAutoResetEventasyncopsAreDone=newAutoResetEvent(false);
counter=newCounter();
for(intthreadNum=0;
threadNumthreadNum++){ThreadPool.QueueUserWorkItem(newWaitCallback(UpdateResource),threadNum);}asyncopsAreDone.WaitOne();}staticvoidUpdateResource(objectstate){intthreadNum=(int)state;if((threadNum%2)!=0)counter.Read(threadNum);elsecounter.Increment(threadNum);if((Interlocked.Decrement(refnumAsyncops))==0)asyncopsAreDone.Set();}}} 5)多线程与Windows窗体控件Windows窗体控件只能在创建它们的线程上执行。如果要从后台线程获取或设置某个控件的属性,或调用该控件的方法,则必须把调用封送到创建该控件的线程。试以进度条控件ProgressBar为例进行编程。创建windows项目ProgressLx,代码可参考P198--199。请运行程序,注意观察效果。usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Windows.Forms;usingSystem.Threading; namespaceProgressLx{publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}ThreadtimerThread;privatevoidForm1_Load(objectsender,EventArgse){timerThread=newThread(newThreadStart(ThreadProc));timerThread.IsBackground=true;timerThread.Start();}publicvoidThreadProc(){try{MethodInvokermi=newMethodInvoker(this.UpdateProgress);while(true){this.BeginInvoke(mi);Thread.Sleep(500);}}catch(ThreadInterruptedExceptione){}catch(Exceptionwe){}}privatevoidUpdateProgress(){if(progressBar1.Value==progressBar1.Maximum){progressBar1.Value=progressBar1.Maximum;}progressBar1.PerformStep();}publicvoidDispose(){if(timerThread!=null){timerThread.Interrupt();timerThread=null;}}privatevoidprogressBar1_Click_1(objectsender,EventArgse){}}} 3、异步编程训练1)使用回调的方式实现文件的异步读取。代码可参考P203—204创建控制台项目CallbackReadFile,在Program.cs中编写代码。usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.IO;namespaceCallbackReadFile{classProgram{classMyState{publicstringfilename;publicMyState(stringfilename){this.filename=filename;}}staticbyte[]buffer=newbyte[2048];staticstringfilename="MyFile.txt";staticStreamaStream;staticMyStatemyState=newMyState(filename);staticvoidMain(string[]args){aStream=File.OpenRead(myState.filename);AsyncCallbackmyCallback=newAsyncCallback(OnReadDone);IAsyncResultar=aStream.BeginRead(buffer,0,buffer.Length,myCallback,(object)myState);Console.ReadLine();}staticvoidOnReadDone(IAsyncResultar){intbyteCount=aStream.EndRead(ar);Console.WriteLine("Filenameread:{0}",((MyState)(ar.AsyncState)).filename);aStream.Close();EncodingencodingGB2312=Encoding.GetEncoding("GB2312");Console.WriteLine(encodingGB2312.GetString(buffer));}}}2)使用轮询的方式实现文件的异步读取。代码可参考P203—204创建控制台项目PollingReadFile,在Program.cs中编写代码。usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.IO;namespacePollingReadFile{classProgram{classMyState{publicstringfilename;publicMyState(stringfilename){this.filename=filename;}}staticbyte[]buffer=newbyte[2048];staticstringfilename="MyFile.txt";staticStreamaStream;staticMyStatemyState=newMyState(filename);staticvoidMain(string[]args){aStream=File.OpenRead(myState.filename);IAsyncResultar=aStream.BeginRead(buffer,0,buffer.Length,null,(object)myState);while(!ar.IsCompleted){}intbyteCount=aStream.EndRead(ar);Console.WriteLine("Filenameread:{0}",((MyState)(ar.AsyncState)).filename);aStream.Close();EncodingencodingGB2312=Encoding.GetEncoding("GB2312");Console.WriteLine(encodingGB2312.GetString(buffer));}}}3)试说明代码中出现的AsyncCallback、BeginRead、EndRead、IasyncResult、AsyncState的含义。 【4】思考题1、publicdelegatevoidMyDelegate1(strings);该语句是一条委托声明,说明其含义?2、如何在.NETFramework中启动线程、管理线程和终止线程?3、获取异步操作的结果有哪些方法?
threadNum++)
ThreadPool.QueueUserWorkItem(
newWaitCallback(UpdateResource),threadNum);
asyncopsAreDone.WaitOne();
staticvoidUpdateResource(objectstate)
intthreadNum=(int)state;
if((threadNum%2)!
=0)counter.Read(threadNum);
elsecounter.Increment(threadNum);
if((Interlocked.Decrement(refnumAsyncops))==0)
asyncopsAreDone.Set();
5)多线程与Windows窗体控件
Windows窗体控件只能在创建它们的线程上执行。
如果要从后台线程获取或设置某个控件的属性,或调用该控件的方法,则必须把调用封送到创建该控件的线程。
试以进度条控件ProgressBar为例进行编程。
创建windows项目ProgressLx,代码可参考P198--199。
请运行程序,注意观察效果。
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Windows.Forms;
namespaceProgressLx
publicpartialclassForm1:
Form
publicForm1()
InitializeComponent();
ThreadtimerThread;
privatevoidForm1_Load(objectsender,EventArgse)
timerThread=newThread(newThreadStart(ThreadProc));
timerThread.IsBackground=true;
timerThread.Start();
publicvoidThreadProc()
try{
MethodInvokermi=newMethodInvoker(this.UpdateProgress);
while(true)
this.BeginInvoke(mi);
Thread.Sleep(500);
catch(ThreadInterruptedExceptione)
catch(Exceptionwe)
privatevoidUpdateProgress()
if(progressBar1.Value==progressBar1.Maximum)
progressBar1.Value=progressBar1.Maximum;
progressBar1.PerformStep();
publicvoidDispose()
if(timerThread!
=null)
timerThread.Interrupt();
timerThread=null;
privatevoidprogressBar1_Click_1(objectsender,EventArgse)
3、异步编程训练
1)使用回调的方式实现文件的异步读取。
代码可参考P203—204
创建控制台项目CallbackReadFile,在Program.cs中编写代码。
usingSystem.IO;
namespaceCallbackReadFile
classMyState
publicstringfilename;
publicMyState(stringfilename)
this.filename=filename;
staticbyte[]buffer=newbyte[2048];
staticstringfilename="MyFile.txt";
staticStreamaStream;
staticMyStatemyState=newMyState(filename);
aStream=File.OpenRead(myState.filename);
AsyncCallbackmyCallback=newAsyncCallback(OnReadDone);
IAsyncResultar=aStream.BeginRead(buffer,0,buffer.Length,myCallback,(object)myState);
staticvoidOnReadDone(IAsyncResultar)
intbyteCount=aStream.EndRead(ar);
Console.WriteLine("Filenameread:
{0}",((MyState)(ar.AsyncState)).filename);
aStream.Close();
EncodingencodingGB2312=Encoding.GetEncoding("GB2312");
Console.WriteLine(encodingGB2312.GetString(buffer));
2)使用轮询的方式实现文件的异步读取。
创建控制台项目PollingReadFile,在Program.cs中编写代码。
namespacePollingReadFile
IAsyncResultar=aStream.BeginRead(buffer,0,buffer.Length,null,(object)myState);
while(!
ar.IsCompleted)
3)试说明代码中出现的AsyncCallback、BeginRead、EndRead、IasyncResult、AsyncState的含义。
【4】思考题
1、publicdelegatevoidMyDelegate1(strings);该语句是一条委托声明,说明其含义?
2、如何在.NETFramework中启动线程、管理线程和终止线程?
3、获取异步操作的结果有哪些方法?
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2