When writing WinForm program, we often need to use the progress bar. Let me share various methods I use to deal with the progress bar.
Create a Winform form application project. Add a new form (progressForm.cs) to host the progress bar; Add a progress bar control to the progressForm form.
1, Single threaded progress bar
Add a method Addprogess to progressForm.cs to push the progress bar.
public void Addprogess() { progressBar1.Value++; }
The next step is to add a startup method in the main form. First add a Boutton control to start.
Add the following code to the button click event.
private void button1_Click(object sender, EventArgs e) { progressForm progress = new progressForm(); progress.Show(); for (int i = 0; i < 100; i++) { progress.Addprogess(); Thread.Sleep(50); } progress.Close(); }
In the above, a for loop is used to simulate the methods that need to insert data or execute in the actual project. Thread. See (50) suspends the thread for 50 milliseconds to simulate the time required for each operation in the actual project.
Such a progress bar is completed. Is it easy to add a progress bar in Winform? With no more than 10 lines of code, you can complete a progress bar.
After completing the progress bar, although it seems to work normally, we will find a problem: when the progress bar is executed, we can't operate the main form, which is also a very troublesome problem. Of course, in the beginner stage, many people will not consider this problem. But after our work, when we finish a program, we need to consider the performance and ease of use of the program. Then we need to make improvements.
2, Multithreaded progress bar
First, simply popularize multithreading:
Thread: it is the basic execution unit in the process and the basic unit of CPU time allocated by the operating system. A process can contain several threads. The first thread executed at the process entry is regarded as the main thread of the process. In. NET applications, the Main() method is used as the entry. When this method is called, the system will automatically create a main thread. Threads are mainly composed of CPU registers, call stacks, and Thread Local Storage (TLS). The CPU register is mainly used to record the status of the currently executing thread, the call stack is mainly used to maintain the memory and data called by the thread, and the TLS is mainly used to store the status information of the thread.
Advantages of multithreading: it can complete multiple tasks at the same time; It can make the response speed of the program faster; You can allow tasks that occupy a lot of processing time or tasks that are not currently being processed to regularly give processing time to other tasks; The task can be stopped at any time; You can set the priority of each task to optimize program performance.
Then someone may ask: why can multithreading execute? To sum up, there are two reasons:
1. The CPU runs too fast and the hardware processing speed can't keep up, so the operating system performs time slice management. In this way, from a macro point of view, it is multi-threaded concurrency, because the CPU speed is too fast to notice, and it seems that different operations are performed at the same time. But from a microscopic point of view, there can only be one thread processing at a time.
2. At present, computers are multi-core and multi CPU. A CPU can only run one thread at the same time, but multiple CPUs can run multiple threads at the same time.
However, Although multithreading has many advantages, it must also be recognized that multithreading may have adverse aspects that affect the system performance in order to use threads correctly. The disadvantages are as follows:
(1) Threads are also programs, so threads need to occupy memory. The more threads, the more memory they occupy.
(2) Multithreading requires coordination and management, so it takes CPU time to track threads.
(3) The access to shared resources between threads will affect each other, and the problem of contention for shared resources must be solved.
(4) Too many threads will lead to too complex control, which may eventually lead to many program defects.
When an executable is started, a Main thread is created. By default, the C# program has a thread that executes the code that starts and ends with the Main method in the program. Each command directly or indirectly executed by the Main () method is executed by the default thread (Main thread). When the Main () method returns, this thread will also terminate.
A process can create one or more threads to execute part of the program code associated with the process. In C#, threads are handled using the thread class, which is in the System.Threading namespace. When using the thread class to create a thread, you only need to provide a thread entry, which tells the program what to do with this thread. You can create a thread by instantiating an object of the thread class. When you create a new thread object, a new managed thread is created. Thread class receives a ThreadStart delegate or the constructor of ParameterizedThreadStart delegate. The delegate wraps the method called by the new thread when the Start method is called. The example code is as follows:
Thread thread=new Thread(new ThreadStart(method)); // Create thread
thread.Start(); // Start thread
The above code instantiates a Thread object, indicates the method() to be called, and then starts the Thread. The method as a parameter in the ThreadStart delegate does not require a parameter and does not return a value. Parametrizedthreadstart delegates an object as a parameter. Using this parameter, you can easily pass parameters to threads. The example code is as follows:
Thread thread=new Thread(new ParameterizedThreadStart(method));// Create thread
thread.Start(3); // Start thread
To create a multithread:
1. Write the method to be executed by the thread
2. Instantiate the Thread class and pass in a delegate to the method to be executed by the Thread. (at this time, the Thread has been generated, but it has not yet run)
3. Call the Start method of the Thread instance to mark that the Thread can be executed by the CPU, but the specific execution time is determined by the CPU
The above explanation of multithreading refers to:( C # multithreading)
After reading the above explanation, you should have a general understanding of multithreading, and then start to modify the code in the bouton click event.
private void button1_Click(object sender, EventArgs e) { Thread progressthread = new Thread(new ParameterizedThreadStart(thread)); progressthread.Start(); } public void thread(object length) { progressForm progress = new progressForm(); progress.Show(); for (int i = 0; i < 100; i++) { progress.Addprogess(); Thread.Sleep(50); } progress.Close(); }
As you can see from the code, we just added an additional thread() method. In this method, we put the part of the code originally put in button_Click.
Thread this method is used to open up a new thread and put the progress bar into the new thread. After modification, it is found that when the progress bar is loaded, it can also operate the main window at the same time, so as to avoid the program entering the "fake death" state. This greatly improves the users' experience of program operation.
There seems to be no problem coming here. There is really no problem at the application level, but I always think there is a problem with the program itself. Personally, the business handled by the main thread should not be placed on the thread where the progress bar is located. The thread where the progress bar is located only needs to be responsible for the progress bar. We can put the main business into the main thread or open a new thread to handle it.
3, Use delegate and invoke methods to implement cross thread UIl control to implement the progress bar
This is to further improve the progress bar. Although the above progress bar uses threads, when we run, we will find that when we mouse to the progress bar window, it always becomes loaded. I'm not sure. It's probably related to thread blocking. Anyway, this situation seems to be seriously inconsistent with our requirements for the program. After all, it looks like a bug.
Let's change the name of the bouton control above.
Boutton: [Name: StartButton ]
Add a label control (showing the number of files processed):
Name: DataNumber
using System; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApp8 { public partial class Form1 : Form { public delegate void addProgress();//Create delegate progressForm progress;//Declare a progressForm window variable public int n;//Declare a variable to display the number of files processed public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { n = 0;//Assign a value to variable n, and each click of the button can initialize the value of n (if not initialized, the value of DataNumber.Text at the beginning of the second time will accumulate from the value at the end of the last time) progress = new progressForm();//Instantiate progressForm progress.Show();//Show progressForm window instances Thread progressthread = new Thread(new ParameterizedThreadStart(thread));//Create thread progressthread.Start();//Start thread } public void thread(object length) { int temp = 1;//Intermediate variable, the actual value is equal to the value of the progress bar for (int i = 0; i < 450; i++)//Simulate the use environment to process 450 pieces of information { if (i / 4.5 >temp)//The maximum value of the progress bar value is 100. Control to call the method every 4.5 data processed to increase the value by 1 { this.Invoke(new addProgress( progress.Addprogess));//invoke method: executes the specified delegate synchronously temp++; } this.Invoke(new addProgress(DataNumberAdd));//Synchronous execution delegation Thread.Sleep(50);//Suspend the thread for 50 milliseconds to slow down the change of the progress bar } this.Invoke(new addProgress(progress.Close));//Close the progress bar window by executing the delegate synchronously } /// <summary> ///DataNumber auto increment method /// </summary> public void DataNumberAdd() { n++; DataNumber.Text = n.ToString();//Change the value of DataNumber } } }
4, Use asynchronous delegate execution threads to complete the progress bar
Asynchronous delegation doesn't need much explanation because it's not easy to explain. If you want to further study. Net, you can search the corresponding information online.
In fact, asynchronous delegation is not suitable for the progress bar. After all, the progress bar is used to visually reflect the progress of data loading or data processing. This is a synchronous reflection process, and asynchronous delegation is completely out of tune. This is only for understanding. If it is really practical, this will not be considered.
using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Windows.Forms; namespace TheardProgress { public partial class Form1 : Form { public List<int> Sum = new List<int>(); public delegate int addProgress(int i); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Thread progressthread = new Thread(new ParameterizedThreadStart(thread)); progressthread.Start(); label1.Text = Sum.Count().ToString(); } public void thread(object length) { bool a = true; progressForm progress = new progressForm(); progress.Show(); addProgress pro = add; for (int i = 0; i < 100; i++) { IAsyncResult asyncResult = pro.BeginInvoke(i, null, null); while (!asyncResult.IsCompleted) { Thread.Sleep(100); } //progress.Addprogess(); progress.labletxt(pro.EndInvoke(asyncResult)); } } public int add(int i) { Sum.Add(i); return Sum.Count(); } } }
Check whether the delegate has completed the task through the IsComplete property of the IAsyncResult interface. The EndInvote method gets the execution result. Sum simulates the execution progress of the main business. In this way, creating an IAsyncResul instance in the progress bar thread can asynchronously call the instance pro of addProgress delegate. Pro implements the main business, and uses while() {} to monitor whether each group of business is completed. The for loop indicates that all business cycles are completed. After completing each group of business, the progress.labletxt () method will be executed to update the progress of the progress bar.
Add the labletxt () method in progressForm,
public void labletxt( int value) { progressBar1.Value = value; }
5, Using Async,await completes the progress bar
First, describe my understanding of these two keywords:
Async means asynchronous. As long as the keyword is added to the method, the method will run on a new child thread every time the method is executed.
await means to wait. It means to wait for the method behind the keyword to run before continuing to execute the following logic in the thread.
Main form:
using System; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApp21 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } int Number = 0;//Number indicates the amount of tasks completed. This number will be directly transferred to Form2 (progress bar bearing window) as the Value of the progress bar public async void WorkAsync() { //async keyword represents the synchronization method Form2 progress = new Form2(); progress.Show(); for (int i = 0; i < 100; i++) { //Wait for the results returned after each part of the task is completed int num = await Task.Run(() => { //Task logic Thread.Sleep(1000); return Number++;//After completing the task, Number is added automatically }); progress.SetProgerssBar(num);//Set progress bar value } Number = 0; } private void button1_Click(object sender, EventArgs e) { WorkAsync(); } } }
Progress bar form:
using System.Windows.Forms; namespace WindowsFormsApp21 { public partial class Form2 : Form { public Form2() { InitializeComponent(); } public void SetProgerssBar(int Number) { progressBar1.Value = Number; } } }
Even if such a progress bar is completed, it may still have some defects to be improved. In fact, a small progress bar still needs a lot of hard knowledge if it is to be done well. knowledge has no limit.