You can write applications that can execute multiple tasks at the same time. This capability (called "multi-threaded processing" or "free-threaded processing") is a powerful method for designing processor-intensive components that require user input. The component used to calculate the payroll information is an example of a component that may be processed using multiple threads. This component can process user input to the database data in one thread, and execute payroll calculations that frequently use processors on the other thread. By running these processes on different threads, you can enter other data without waiting for the computer to complete the computation. In this walkthrough, a simple multi-threaded component is created, which can execute several complex computations at the same time.
Create a project
The application will include a single form and a component. The user enters a value and instructs the component to start calculation. The form then receives the value from this component and displays it in the tag control. This component will execute frequent processor computing and notify the form after completion. You will create a public variable in the component to save the value received from the user interface. At the same time, you will also implement some methods in the component to perform calculations based on the values of these variables.
Note that although functions are generally more desirable for calculating values, they cannot pass parameters between threads or return values. There are many simple methods to provide the value to the thread and receive the value from the thread. In this demonstration, the value is returned to the user interface by updating the public variables. After the thread is executed, the main program is notified by events.
Create a form
Create a new "Windows application" project.
Name the application Calculations and rename Form1.cs to frmCalculations. cs.
This form is used as the main user interface of the application.
Double-click the form on the designer to open the code editor. In the "edit" menu, select "search and replace", and then select "replace ". Use replace all to replace Form1 with frmCalculations.
In Solution Explorer, right-click "frmCalculations. cs" and select "view designer ". Open the designer.
Add five Label controls, four Button controls, and one TextBox Control to the form.
Set Properties for these controls as follows:
Widget |
Name |
Text |
Label1 |
LblFactorial1 |
(Blank) |
Label2 |
Lblfactorial |
(Blank) |
Label3 |
LblAddTwo |
(Blank) |
Label4 |
LblRunLoops |
(Blank) |
Label5 |
LblTotalCalculations |
(Blank) |
Button1 |
BtnFactorial1 |
Factorial |
Button2 |
Btnfactorial |
Factorial-1 |
Button3 |
BtnAddTwo |
Add Two |
Button4 |
BtnRunLoops |
Run a Loop |
Textbox1 |
TxtValue |
(Blank) |
Create a Calculator component
Select "add component" from the "project" menu ".
Name the component Calculator.
Add public variables to the Calculator component
Open the code editor for Calculator.
Add statements for creating public variables that are used to pass values from frmCalculations to each thread.
The variable varTotalCalculations retains the cumulative value of the total number of computations executed by this component, while other variables receive values from the form.
Public int varAddTwo; Public int varFact1; Public int varFact2; Public int varLoopValue; Public double varTotalCalculations = 0; |
Add methods and events to the Calculator component
Delegates an event declaration. The component uses these events to pass values to the form.
Note that although you will declare four events, you only need to create three delegates because the two events have the same signature.
Next, enter the following code at the bottom of the variable declaration entered in the previous step:
// 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 ); |
Declare events that the component will use to communicate with the application. To achieve this, add the following code below the code entered in the previous step.
Public event FactorialCompleteHandler FactorialComplete; Public event FactorialCompleteHandler FactorialMinusOneComplete; Public event AddTwoCompleteHandler AddTwoComplete; Public event LoopCompleteHandler LoopComplete; |
Next, enter the following code at the bottom of the code you typed in the previous step:
// 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. VarTotalCalculations + = 1; VarTotalAsOfNow = varTotalCalculations; } // Signals that the method has completed, and communicates // Result and a value of total calculations saved med 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 ); } |
Transmit user input to components
The next step is to add code to frmCalculations to receive user input, receive and transmit values from and to the Calculator component.
Implement the front-end functions of frmCalculations
Open frmCalculations in the code editor.
Find the public class frmCalculations statement. Enter the following:
Find the constructor. Then add the following lines before:
// Creates a new instance of Calculator. Calculator1 = new Calculator (); |
Click each button in the designer to generate an outline of the code for each control's click event handler, and add code to create these handlers.
After that, click the event handler in the following format:
Private void btnfactorial#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_C |