Implement background processes in Visual Basic. NET (1)

Source: Internet
Author: User

Abstract:Rocky Lhotka recommends and implements a structured architecture example, which can act as a medium between the auxiliary thread and UI thread, thus simplifying the process of writing multi-thread auxiliary code and UI to control it. This architecture includes downloadable code examples, which can be adjusted based on your application needs.

With multithreading, applications can execute multiple tasks at the same time. With multithreading, one thread can run the user interface, and another thread can perform complex operations or operations in the background. Because Microsoft®Visual Basic®. NET supports multithreading, so we can easily obtain this function.

However, multithreading also has its shortcomings. When an application uses multiple threads, we always encounter the problem that multiple threads attempt to interact with the same data or resources at the same time. In this case, the problem becomes very complex and difficult to debug.

What's worse, multi-threaded Code usually seems to run normally during initial development, however, in the production process, an error occurs because multiple threads interact with the same data or resources at the same time. This increases the risk of multi-threaded programming!

Because it is very difficult to design and debug multi-threaded applications, Microsoft has created the "single-threaded unit" (STA) concept in COM. Visual Basic 6 code is always run in STA, so you only need to consider a single thread for the code. This completely avoids the problems caused by data sharing or resources, but it also means that we must take strict measures to take advantage of multithreading.

. NET does not have this common problem in Stas. All. NET code is run in the AppDomain that allows multi-thread operations. This means that Visual Basic. NET code is also running in AppDomain, so you can use multithreading. Obviously, you must write code carefully at any time to avoid conflicts between threads.

To avoid conflicts between threads, the simplest way is to ensure that multiple threads will never interact with the same data or resources. Although not possible, it is recommended that you avoid or minimize the use of shared data or resources during design for any multi-threaded application.

This not only simplifies the coding and debugging process, but also improves the performance. To resolve conflicts between threads, you must use the synchronization technology that can block or suspend other threads before a thread completes the operation. Blocking a thread is to make the thread idle without any operation, thus reducing performance.

Cancel button and Status display

There are many reasons for using multithreading in applications, but the most common reason is that we need to execute a task that runs for a long time, on the other hand, it is expected that some or all user interfaces will remain in the response state for the user.

At least we should makeCancelThe cancel button is always in the response state, allowing users to tell the system that they want to terminate long-running tasks.

In Visual Basic 6, we try to useDoEvents, Timer control, and many other methods. The operation in Visual Basic. NET is much simpler, because we can use multithreading. In addition, we can complete this operation with care and will not complicate code or debugging.

To be successfully implemented in a multi-threaded EnvironmentCancel(Cancel) button, the key is to rememberCancel(Button) only applies to "request" to cancel the task. The background task determines when to stop.

If we implement a process that can directly stop the background processCancelThe cancel button may stop sensitive operations or shut down important resources (such as file processing programs or database connections) in the background process) stop it before. This may cause serious consequences, resulting in crashes, unstable application behavior, or full collapse of the application.

Therefore,CancelThe cancel button is only used to stop background tasks. A background task can check whether a request to cancel an operation exists at a certain time point. If a request to cancel an operation is detected, the background thread can release all resources, stop all important operations, and terminate normally.

Although the cancellation request is very important, we hope to display the background process status information through the UI. Status information can be a message in text format, a percentage of completed tasks, or two messages are displayed at the same time.

To be implemented in Visual Basic. NETCancelThe most complex problem we face when a button or status is displayed is that the Windows form library is not secure for threads. This means that only the thread that creates a form can interact with the form or its control. Other threads cannot interact with the form or its controls safely.

However, we cannot avoid writing code that interacts with a given form using multiple threads. Therefore, the running may have unpredictable consequences, or even cause application crashes.

This requires us to be careful when coding and ensure that only our UI threads interact with the UI. Therefore, we can establish a simple architecture to manage the interaction between the background guides and UI threads. If it can be implemented, we can clearly understand that we are using multithreading in both the UI code and the code of long-running tasks.

Threads and objects

If you want to create a background process and enable it to run its own data on its own thread, the simplest way is to create an object dedicated to this background process. Although not necessarily possible, it is a positive goal because it can greatly simplify the process of creating multi-threaded applications.

If the background thread runs in its own object, the background thread can use the instance variable of this object (the variable declared in the class ), there is no need to worry that these variables will be used by other threads. For example, consider the following classes:

Public Class Worker  Private mInner As Integer  Private mOuter As Integer  Public Sub New(ByVal InnerSize As Integer, ByVal OuterSize As Integer)    mInner = InnerSize    mOuter = OuterSize  End Sub  Public Sub Work()    Dim innerIndex As Integer    Dim outerIndex As Integer    Dim value As Double    For outerIndex = 0 To mOuter      For innerIndex = 0 To mInner         do some cool calculation here        value = Math.Sqrt(CDbl(innerIndex - outerIndex))      Next    Next  End SubEnd Class

This class is suitable for running in background threads and can be started using the following code:

Dim myWorker As New Worker(10000000, 10)Dim backThread As New Thread(AddressOf myWorker.Work)backThread.Start()

WorkerThe instance variables in the class can store their data. Background threads can safely use these variables (MInnerAndMOuter) To ensure that other threads do not access these variables at the same time.

We can useConstructorMethod to initialize the object with any starting data. Before starting the background thread, our main application code will create an instance of this object and initialize it using the data to be operated by the background thread.

The background thread will obtainWorkMethod address, and then start. This thread will immediately run code inside the object and use the dedicated data of the object.

Because the object is self-contained, we can create multiple objects, each of which runs on its own thread and is relatively independent of each other.

However, this implementation scheme is not ideal. The UI cannot obtain the status of the background process. We have not implemented any mechanism to enable the UI to request termination of background processes.

To solve the preceding two problems, the background thread and UI thread must interact in some way. This interaction method is very complex, so it is best to put the interaction in a class in some way, so that the UI and auxiliary Code do not have to worry about details.

Architecture

We can create an architecture that allows the UI and auxiliary code to interact with each other without threads. In fact, we can achieve this goal, and implement an architecture that can implement complex code in some way, which can be used to manage or control background threads and Their UI interactions.

Let's first discuss the architecture and then how to design and implement the Code. You can download this code from the links in this article and explain how to use the sample application of this Code.

Generally, an application starts a single thread to open the user interface. We name it "UI thread" for your understanding. "UI thread" is the only thread in many applications, so it must process the UI and complete all operations.

However, now we create a "auxiliary thread" to perform some background operations so that the UI thread can process the user interface in a centralized manner. In this way, even if the auxiliary thread is busy, the UI thread can respond to the user.

We insert a layer of code between the UI thread and the auxiliary thread to act as an interface between the UI and the auxiliary code. This code is essentially a "controller" used to manage and control the auxiliary threads and their interaction with the UI.

Figure 1 UI thread, Controller, and auxiliary thread

The Code contained in the controller can safely start the auxiliary thread, transfer any status message from the auxiliary thread to the UI thread, and transfer any cancellation request from the UI thread back to the auxiliary thread. The UI code and the auxiliary Code cannot interact directly. They usually need to interact through the Controller code.

Except for the period of time when the auxiliary thread is activated "before" and "after", the UI code canWorkerObjects. The UI can be created and initialized before the auxiliary thread is started.WorkerObject. After terminating the auxiliary thread, the UI canWorkerAny value in the object. From the UI perspective, the following event streams will be formed:

  1. CreateWorkerObject.
  2. InitializationWorkerObject.
  3. CallControllerTo start the auxiliary thread.
    1. WorkerThe object will passControllerSend status information to the UI.
    2. You can useControllerSend the cancel requestWorkerObject.
  4. WorkerAfter the operation, the object passesControllerNotification UI.
  5. The value can be directly fromWorkerObject.

The UI code cannot matchWorkerIn addition to the restrictions on direct interaction of objects, there are no special coding requirements for the UI. Even if you are running background operations, the UI will remain active and responsive to users.

SlaveWorkerFrom the object perspective, the following event streams are formed:

  1. Create UI codeW

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.