当前位置:首页 > 全部子站 > 备课网 > 学院

运用VC# 创作简单的多线程组件

来源:长理培训发布时间:2017-08-20 19:54:53

  可以编写能同时执行多个任务的应用程序。此能力(称为“多线程处理”或“自由线程处理”)是设计处理器密集型且要求用户输入的组件的强大方法。计算工资表信息的组件就是一个可能利用多线程处理的组件示例。该组件可以在一个线程上处理用户输入到数据库的数据,而在另一个线程上执行频繁使用处理器的工资表计算。通过在不同的线程上运行这些进程,用户不必等到计算机完成计算,就可以输入其他数据。在本演练中,将创建一个简单的多线程组件,该组件可以同时执行若干个复杂计算。 

创建项目 

   应用程序将包括单个窗体和一个组件。用户将输入值并指示该组件开始计算。然后,窗体将接收来自该组件的值,将其显示在标签控件中。该组件将执行频繁使用处理器的计算,并在完成后通知窗体。您将在组件中创建公共变量,用以保存从用户界面收到的值。同时,您还将在组件中实现一些方法,根据这些变量的值执行计算。 

   注意 尽管对于计算值的方法来说,函数通常更为可取,但不能在线程之间传递参数,也不能返回值。有很多向线程提供值和从线程接收值的简单方法。在本演示中,将通过更新公共变量将值返回到用户界面,当线程执行完毕后,使用事件来通知主程序。 

创建窗体 

   创建新的“Windows 应用程序”项目。 

   将应用程序命名为 Calculations,并将 Form1.cs 重命名为 frmCalculations.cs。 

   该窗体将用作应用程序的主用户界面。 

   双击设计器上的窗体以打开代码编辑器。在“编辑”菜单中,选择“查找和替换”,然后选择“替换”。使用“全部替换”将 Form1 替换为 frmCalculations。 

   在“解决方案资源管理器”中,右击“frmCalculations.cs”并选择“视图设计器”。设计器打开。 
向窗体中添加 5 个 Label 控件、4 个 Button 控件和 1 个 TextBox 控件。 

   为这些控件设置属性,如下所示: 

控件 名称 文本 Label1 lblFactorial1 (空白) Label2 lblFactorial2 (空白) Label3 lblAddTwo (空白) Label4 lblRunLoops (空白) Label5 lblTotalCalculations (空白) Button1 btnFactorial1 Factorial Button2 btnFactorial2 Factorial - 1 Button3 btnAddTwo Add Two Button4 btnRunLoops Run a Loop Textbox1 txtValue (空白) 
创建 Calculator 组件 

   从“项目”菜单中选择“添加组件”。 

   将组件命名为 Calculator。 

   向 Calculator 组件添加公共变量 

   为 Calculator 打开代码编辑器。 

   添加创建公共变量的语句,这些变量用于将值从 frmCalculations 传递给每个线程。 

   变量 varTotalCalculations 将保留该组件执行的计算总数的累计值,而其他变量将接收来自窗体的值。 

public int varAddTwo; 
public int varFact1; 
public int varFact2; 
public int varLoopValue; 
public double varTotalCalculations = 0; 
向 Calculator 组件添加方法和事件 

   为事件声明委托,组件将使用这些事件向窗体传递值。 

   注意 尽管您将声明 4 个事件,但由于其中的两个事件将具有相同的签名,因此只需要创建 3 个委托。 

   紧接着上一步输入的变量声明的下方,键入下列代码: 

// This delegate will be invoked with two of your events. 
public delegate void FactorialCompleteHandler(double Factorial, double TotalCalculations); 
public delegate void AddTwoCompleteHandler(int Result, double TotalCalculations); 
public delegate void LoopCompleteHandler(double TotalCalculations, int Counter); 
   声明组件将用来与应用程序进行通信的事件。为实现此目的,紧接着上一步输入的代码的下方,添加下列代码。 

public event FactorialCompleteHandler FactorialComplete; 
public event FactorialCompleteHandler FactorialMinusOneComplete; 
public event AddTwoCompleteHandler AddTwoComplete; 
public event LoopCompleteHandler LoopComplete; 
   紧接着上一步键入的代码的下方,键入下列代码: 

// This method will calculate the value of a number minus 1 factorial 
// (varFact2-1!). 
public void FactorialMinusOne() 

double varTotalAsOfNow = 0; 
double varResult = 1; 
// Performs a factorial calculation on varFact2 - 1. 
for (int varX = 1; varX <= varFact2 - 1; varX++) 

varResult *= varX; 
// Increments varTotalCalculations and keeps track of the current 
// total as of this instant. 
varTotalCalculatio

 

[1] [2] [3] [4] [5] [6] 下一页  

 

ns += 1; 
varTotalAsOfNow = varTotalCalculations; 

// Signals that the method has completed, and communicates the 
// result and a value of total calculations performed up to this 
// point. 
FactorialMinusOneComplete(varResult, varTotalAsOfNow); 


// This method will calculate the value of a number factorial. 
// (varFact1!) 
public void Factorial() 

double varResult = 1; 
double varTotalAsOfNow = 0; 
for (int varX = 1; varX <= varFact1; varX++) 

varResult *= varX; 
varTotalCalculations += 1; 
varTotalAsOfNow = varTotalCalculations; 

FactorialComplete(varResult, varTotalAsOfNow); 


// This method will add two to a number (varAddTwo+2). 
public void AddTwo() 

double varTotalAsOfNow = 0; 
int varResult = varAddTwo + 2; 
varTotalCalculations += 1; 
varTotalAsOfNow = varTotalCalculations; 
AddTwoComplete(varResult, varTotalAsOfNow); 


// This method will run a loop with a nested loop varLoopValue times. 
public void RunALoop() 

int varX; 
double varTotalAsOfNow = 0; 
for (varX = 1; varX <= varLoopValue; varX++) 

// This nested loop is added solely for the purpose of slowing down 
// the program and creating a processor-intensive application. 
for (int varY = 1; varY <= 500; varY++) 

varTotalCalculations += 1; 
varTotalAsOfNow = varTotalCalculations; 


LoopComplete(varTotalAsOfNow, varLoopValue); 

将用户输入传输到组件 

   下一步是向 frmCalculations 添加代码,以接收用户输入,以及从 Calculator 组件接收值和向它传输值。 

   实现 frmCalculations 的前端功能 

   在代码编辑器中打开 frmCalculations。 

   找到 public class frmCalculations 语句。紧接着 { 的下方键入: 

Calculator Calculator1; 
   找到构造函数。紧接着 } 之前,添加以下行: 

// Creates a new instance of Calculator. 
Calculator1 = new Calculator(); 
   在设计器中单击每个按钮,为每个控件的单击事件处理程序生成代码大纲,并添加代码以创建这些处理程序。 

   完成后,单击事件处理程序应该类似于以下形式: 

private void btnFactorial1_Click(object sender, System.EventArgs e) 
// Passes the value typed in the txtValue to Calculator.varFact1. 

Calculator1.varFact1 = int.Parse(txtValue.Text); 
// Disables the btnFactorial1 until this calculation is complete. 
btnFactorial1.Enabled = false; 
Calculator1.Factorial(); 


private void btnFactorial2_Click(object sender, System.EventArgs e) 

Calculator1.varFact2 = int.Parse(txtValue.Text); 
btnFactorial2.Enabled = false; 
Calculator1.FactorialMinusOne(); 

private void btnAddTwo_Click(object sender, System.EventArgs e) 

Calculator1.varAddTwo = int.Parse(txtValue.Text); 
btnAddTwo.Enabled = false; 
Calculator1.AddTwo(); 

private void btnRunLoops_Click(object sender, System.EventArgs e) 

Calculator1.varLoopValue = int.Parse(txtValue.Text); 
btnRunLoops.Enabled = false; 
// Lets the user know that a loop is running 
lblRunLoops.Text

 

上一页  [1] [2] [3] [4] [5] [6] 下一页  

 

= "Looping"; 
Calculator1.RunALoop(); 

   在上一步添加的代码的下方,键入以下代码以处理窗体将从 Calculator1 接收的事件: 

protected void FactorialHandler(double Value, double Calculations) 
// Displays the returned value in the appropriate label. 

lblFactorial1.Text = Value.ToString(); 
// Re-enables the button so it can be used again. 
btnFactorial1.Enabled = true; 
// Updates the label that displays the total calculations performed 
lblTotalCalculations.Text = "TotalCalculations are " + 
Calculations.ToString(); 


protected void FactorialMinusHandler(double Value, double Calculations) 

lblFactorial2.Text = Value.ToString(); 
btnFactorial2.Enabled = true; 
lblTotalCalculations.Text = "TotalCalculations are " + 
Calculations.ToString(); 


protected void AddTwoHandler(int Value, double Calculations) 

lblAddTwo.Text = Value.ToString(); 
btnAddTwo.Enabled = true; 
lblTotalCalculations.Text = "TotalCalculations are " + 
Calculations.ToString(); 


protected void LoopDoneHandler(double Calculations, int Count) 

btnRunLoops.Enabled = true; 
lblRunLoops.Text = Count.ToString(); 
lblTotalCalculations.Text = "TotalCalculations are " + 
Calculations.ToString(); 

   在 frmCalculations 的构造函数中,紧挨在 } 之前添加下列代码,以处理窗体将从 Calculator1 接收的自定义事件: 

Calculator1.FactorialComplete += new 
Calculator.FactorialCompleteHandler(this.FactorialHandler); 
Calculator1.FactorialMinusOneComplete += new 
Calculator.FactorialCompleteHandler(this.FactorialMinusHandler); 
Calculator1.AddTwoComplete += new 
Calculator.AddTwoCompleteHandler(this.AddTwoHandler); 
Calculator1.LoopComplete += new 
Calculator.LoopCompleteHandler(this.LoopDoneHandler); 
测试应用程序 

   现在项目已经创建完毕,该项目将能够执行若干个复杂计算的组件与窗体结合在一起。尽管尚未实现多线程处理功能,但在继续之前应该对项目进行测试,以验证它的功能。 

测试项目 

   从“调试”菜单中选择“启动”。 

   应用程序启动并显示 frmCalculations。 

   在文本框中键入 4,然后单击标记为“添加两个”的按钮。 

   在按钮下方的标签中应该显示数字“6”,在 lblTotalCalculations 中应该显示“Total Calculations are 1”。 

   现在单击标记为“阶乘 - 1”的按钮。 

   该按钮的下方应显示数字“6”,而 lblTotalCalculations 中现在应显示“Total Calculations are 4”。 

   将文本框中的值更改为 20,然后单击标记为“阶乘”的按钮。 

   该按钮的下方显示数字“2.43290200817664E+18”,而 lblTotalCalculations 中现在显示为“Total Calculations are 24”。

 


   将文本框中的值更改为 50000,然后单击标记为“运行循环”的按钮。 

   注意,在此按钮重新启用前有一个短暂然而明显的间隔。此按钮下的标签应显示“50000”,而总的计算次数显示为“25000024”。 

   将文本框中的值更改为 5000000 并单击标记为“运行循环”的按钮,紧接着单击标记为“添加两个”的按钮。再次单击它。 

   直到循环已经完成,该按钮以及窗体上的任何控件才有响应。 

   如果程序只运行单个执行线程,则类似上述示例的频繁使用处理器的计算倾向于占用该程序,直到计算已经完成。在下一节中,您将向应用程序添加多线程处理功能,以便一次可以运行多个线程。
添加多线程处理功能 

   上面的示例演示了只运行单个执行线程的应用程序的限制。在下一节,您将使用 Thread 类对象向组件添加多个执行线程。 

添加 Threads 子例程 

   在代码编辑器中打开 Calculator.cs。 

   在代码顶部附近,找到类声明,紧接着 { 的下方,键入下列代码: 

// Declares the variables you will use to hold your thread objects. 
public System.Threading.Thread FactorialThread; 
public System.Threading.Thread FactorialMinusOneThread; 
public System.Threading.Thread AddTwoThread; 
public System.Threading.Thread LoopThread;

责编:杨粟梅

发表评论(共0条评论)
请自觉遵守互联网相关政策法规,评论内容只代表网友观点,发表审核后显示!

国家电网校园招聘考试直播课程通关班

  • 讲师:刘萍萍 / 谢楠
  • 课时:160h
  • 价格 4580

特色双名师解密新课程高频考点,送国家电网教材讲义,助力一次通关

配套通关班送国网在线题库一套

课程专业名称
讲师
课时
查看课程

国家电网招聘考试录播视频课程

  • 讲师:崔莹莹 / 刘萍萍
  • 课时:180h
  • 价格 3580

特色解密新课程高频考点,免费学习,助力一次通关

配套全套国网视频课程免费学习

课程专业名称
讲师
课时
查看课程
在线题库
面授课程更多>>
图书商城更多>>
在线报名
  • 报考专业:
    *(必填)
  • 姓名:
    *(必填)
  • 手机号码:
    *(必填)
返回顶部