Architecture Design
To implement the behavior we discuss, we obviously need to implementControllerClass. To enable this architecture to be applied in most scenarios, we will also define some formal interfaces.ControllerUsed when interacting with the UI (or client) and the auxiliary thread.
By defining formal interfaces for clients and auxiliary threads, we can use the sameControllerObject, you can also use different UI requirements and differentWorkerObject.
The following UML charts showControllerClass andIClientAndIWorkerInterface. It also displaysIControllerInterface, through which the auxiliary codeControllerObject interaction.
Figure 5: Class charts of the Controller and related interfaces
IClientThe method defined by the interface will beControllerObject call, used to notify the client UIWorkerStart time, end time, and any intermediate status message. It also contains a method to indicate that the secondary Code fails.
In most cases, we can use these methodsControllerThe event that the UI processes when the object is sent. However, it is not easy for the UI thread to correctly handle the event from the auxiliary thread, so we use it as a set of methods for implementation.
It is much easier to make the Controller code (run on the auxiliary code) call these methods in the UI and process them by the UI thread.
Similarly,IWorkerThe interface definesControllerMethod called by the object to allow it to interact with the auxiliary code. UseInitializeThe method can provideControllerObject reference, and useStartMethod to start operations on the background thread.
Because of the way the thread works,StartThe method cannot contain any parameters. When starting a new thread, the address of the method that does not accept any parameters must be passed to the thread.
Please note that,IWorkerInterface does not existCancelOrStopMethod. We cannot force the secondary code to stop, and this is not necessary; however, the secondary code can be usedIControllerInterface inquiryControllerWhether the object has a cancellation request.
IControllerThe interface defines the auxiliary code inControllerMethod called on the object. It allows secondary code checksRunningFlag. If a cancellation request exists,RunningThe flag isFalse. It also allows the Helper code to be notified when the work is completed or cannot be completedControllerAnd allows the use of status messages and completion percentage values (between 0 and 100)Integer) UpdateController.
Finally, we have definedControllerObject. This object contains some methods that can be called by UI code. IncludingStartMethod.ControllerObjectWorkerObject Reference to start background operations. Also includeCancelMethod. The UI can also be checkedRunningAttribute to check whether a cancellation request exists. You can also checkPercentAttribute to view the percentage of completed tasks.
ControllerClassConstructorMethod acceptanceIClientAs a parameter, the UI can also beControllerProvides the form (for processingWorker.
To implement a series of animation points to display thread activity, we will create a simple Windows form control that uses a timer to change a seriesPictureBoxControls.
Implementation Scheme
We will implement this architecture in the Class Library project so that it can be used for applications that need to run background processes.
Open Visual Studio. NET and create a new Class Library application named Background. Because this library contains Windows Forms controls and forms, you need to useAdd References(Add reference) dialog box referenceSystem. Windows. Forms. dllAndSystem. Windows. Drawing. dll. In addition, you can use the Project Properties dialog box to import namespaces within these projects, as shown in figure 6.
Figure 6: Use Project properties to add the project-wide namespace Imports
After this operation is complete, you can start encoding. Let's start with creating an interface.
Interface Definition
InIClientAdd a class to the project, and replace the Code with the following code:
Public Interface IClient Sub Start(ByVal Controller As Controller) Sub Display(ByVal Text As String) Sub Failed(ByVal e As Exception) Sub Completed(ByVal Cancelled As Boolean)End Interface
Then add the nameIWorkerAnd use the following code to replace the Code:
Public Interface IWorker Sub Initialize(ByVal Controller As IController) Sub Start()End Interface
Add the nameIControllerThe Code is as follows:
Public Interface IController ReadOnly Property Running() As Boolean Sub Display(ByVal Text As String) Sub SetPercent(ByVal Percent As Integer) Sub Failed(ByVal e As Exception) Sub Completed(ByVal Cancelled As Boolean)End Interface
At this point, we have defined the interfaces in all class charts described earlier in this article. Now we can implementControllerClass.
Controller class
Now, we can implement the core architecture,ControllerClass. The Code contained in this class can be used to start the auxiliary thread and act as a medium between the UI thread and the auxiliary thread before the auxiliary thread completes.
Add a new class to the project named Controller. AddImportsAnd declare some variables:
Imports System.ThreadingPublic Class Controller Implements IController Private mWorker As IWorker Private mClient As Form Private mRunning As Boolean Private mPercent As Integer
Then you need to declare some delegates. A delegate is a formal pointer to a method, and the delegate of a method must have the same method signature (parameter type, etc.) as the method itself ).
Delegation is widely used. In our example, the delegate is very important, because the delegate enables a thread to call the method on the form and run it on the UI thread of the form. AsIClientAs defined, all three methods to be called on the form must be delegated:
This delegate signature is used with IClient. the signature in Completed matches and is used to safely call the Private Delegate Sub CompletedDelegate (ByVal Cancelled As Boolean) method on the UI thread. the signature in Display matches and is used to safely call the Private Delegate Sub DisplayDelegate (ByVal Text As String) method on the UI thread. the signature in the Failed matches and is used to safely call the Private Delegate Sub FailedDelegate (ByVal e As Exception) method on the UI thread)
IClientAlso definedStartMethod, but this method can be called from the UI thread, so no need to delegate.
The code to be called from the UI thread is written below. The Code includesConstructorMethod,StartAndCancelMethod andPercentAttribute. I put the content inRegionSo that you can clearly understand that they are called from the UI thread.
# Region "code called from UI thread" uses the Client to initialize Controller Public Sub New (ByVal Client As IClient) mClient = CType (Client, Form) End Sub. This method is called by the UI, therefore, it runs on the UI thread. Here we will Start the auxiliary thread Public Sub Start (Optional ByVal Worker As IWorker = Nothing). If the auxiliary thread has been started, if mRunning Then Throw New Exception ("Background process already running") End If mRunning = True stores references to the secondary object and initializes the secondary object, include the reference mWorker = Worker mWorker to the Controller. initialize (Me) creates a background Thread to perform background operations on Dim backThread As New Thread (AddressOf mWorker. start) Start background work backThread. start () tells the client that CType (mClient, IClien T). Start (Me) End Sub this code is called by the UI, so it runs on the UI thread. It only sets the flag of request cancellation Public Sub Cancel () mRunning = False End Sub to return the completion percentage value, and is only called by the UI thread Public ReadOnly Property Percent () as Integer Get Return mPercent End Get End Property # End Region
The only special code here isStartMethod, we can create a helper thread in this method and then start the thread:
Dim backThread As New Thread(AddressOf mWorker.Start) backThread.Start()
To create a thread, you mustWorkerObjectIWorkerTransfer on InterfaceStartMethod address. Then, you only need to callStartMethod to start the operation. In this case, we should pay special attention that the UI should not be directly associatedWorkerInteraction,Worker