Create a displayed form
Finally, we can create a form to start or cancel background processes. This form also displays activity and status information.
Open the Form1 designer and add two buttons (BtnStartAndBtnRequestCancel), Two labels (Label1AndLabel2), A ProgressBar (ProgressBar1) And an ActivityBar (ActivityBar1), 7.
Figure 7: Form1 control layout
This form needs to be implementedIClientToControllerInteraction between objects:
Imports Background
Public Class Form1 Inherits System.Windows.Forms.Form Implements IClient
This form also requiresControllerObject and a flag used to track whether the background operation is active or complete.
Private mController As New Controller(Me) Private mActive As Boolean
Then, we can add a method to implementIClientInterface. We recommend that you put these methods in Region to indicate that they implement secondary interfaces:
#Region " IClient " Private Sub TaskStarted(ByVal Controller As Controller) _ Implements IClient.Start mActive = True Label1.Text = "Starting" Label2.Text = "0%" ProgressBar1.Value = 0 ActivityBar1.Start() End Sub Private Sub TaskStatus(ByVal Text As String) _ Implements IClient.Display Label1.Text = Text Label2.Text = CStr(mController.Percent) & "%" ProgressBar1.Value = mController.Percent End Sub Private Sub TaskFailed(ByVal e As Exception) _ Implements IClient.Failed ActivityBar1.Stop() Label1.Text = e.Message MsgBox(e.ToString) mActive = False End Sub Private Sub TaskCompleted(ByVal Cancelled As Boolean) _ Implements IClient.Completed Label1.Text = "Completed" Label2.Text = CStr(mController.Percent) & "%" ProgressBar1.Value = mController.Percent ActivityBar1.Stop() mActive = False End Sub#End Region
Please note that all the content in this code is irrelevant to the thread, and each part of the code can respond accordingly when we know the background operation status. After each response, we update the display to indicate the status and completion percentage of the process (in the form of text or throughProgressBarDisplay), and start and stopActivityBarControl.
MActiveThe logo is very important. If you close the form when the auxiliary thread is active, the application may be suspended or become unstable. To prevent this situation, we can interruptClosingEvent and cancel the attempt (if the background process is active ).
Private Sub Form1_Closing(ByVal sender As Object, _ ByVal e As System.ComponentModel.CancelEventArgs) _ Handles MyBase.Closing e.Cancel = mActive End Sub
We can also choose to initialize the cancel Operation in this case, but this depends on the specific application requirements.
The rest of the code is for button implementation.ClickEvent.
Private Sub btnStart_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnStart.Click mController.Start(New Worker(2000000, 100)) End Sub Private Sub btnStop_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnStop.Click Label1.Text = "Cancelling ..." mController.Cancel() End Sub
Start(Start) the button is called onlyControllerObjectStartMethod, andWorkerThe instance of the object is passed to it.
You may need to adjust it for initializationWorkerObject value to obtain the desired results on your computer. These specific values provide a good example on a dual-processor P3/450 computer. Obviously, this is only for testing purposes. RealWorkerObjects will implement more meaningful and longer-running processes.
CancelThe cancel button is called.ControllerObjectCancelMethod, and the display is updated to indicate that the request has been canceled. Remember, this is only a request to cancel. It may take some time before the auxiliary thread stops running. It is best to provide immediate feedback to users, at least to let users know that the system has noticed the user's click button operation.
Now we can run the application. ClickStart(Start) button,WorkerYou should start running, and the displayed content will be updated at runtime. You can move the form to any position on the screen or interact with it, because the UI thread is essentially idle and can interact with you at any time.
At the same time, the auxiliary thread performs a lot of complex work in the background, and regularly sends the status update information to the UI thread for display.
Summary
Multithreading is a powerful tool that can be used every time a task needs to run for a long time. We can use it to run the auxiliary code without binding the user interface. But at the same time, it should be noted that multi-threaded operations are very complicated, correct operations are not easy, and debugging is also difficult.
Although not necessarily, we should try to provide a set of independent data that can be operated by each auxiliary thread. To achieve this goal, the simplest way is to create an object for each thread, which contains the data that the thread can operate on and the Code required to complete the work.
By implementing a structured architecture that acts as a medium between the auxiliary thread and UI thread, We can greatly simplify the process of writing multi-threaded code and UI to control it. This article introduces such an architecture that you can use or adjust as needed to meet specific application needs.