Detailed usage of BackgroudWork, examples


1. What is BackgroudWorker?


    1. In short,
        backgroudworkd is an asynchronous single-thread, specially developed for entry-level personnel. A progress bar can also be displayed. The operation is simple and practical, and it is an old technology.
        Note: If you call this thread twice, an error will occur.
        
    
    2. Introduction to backgroundworker
        BackgroundWorker is an auxiliary class provided in the .NET Framework to simplify multi-threaded programming. It allows time-consuming operations to be performed in a background thread while the user interface is updated in the main thread. BackgroundWorker provides a simple way to handle asynchronous operations without blocking the main thread to improve the responsiveness of the user interface.

        General steps for using BackgroundWorker (the following is the dynamic generation of the control, drag and drop the control only look at steps 3-5):

        (1) Instantiate a BackgroundWorker object.
        (2) Register event handlers, such as DoWork (processing time-consuming operations), ProgressChanged (reporting progress updates) and RunWorkerCompleted (cleaning up after the operation is completed).
        (3) Perform operations that need to be completed in the background thread in the DoWork event handler. Progress can be reported using the ReportProgress method.
        (4) Update the interface in the ProgressChanged event handler to reflect the change in progress.
        (5) Perform the cleanup operation and process the results of the operation in the RunWorkerCompleted event handler.

        With BackgroundWorker, you can simplify asynchronous programming, making it more convenient to handle time-consuming operations and update the user interface. However, it should be noted that BackgroundWorker is an older technology, and in more advanced asynchronous programming scenarios, more modern mechanisms and patterns such as Task and async/await may need to be used.
            
    3. Which one is more economical in terms of resource consumption, dynamically generated controls or drag-and-drop controls before writing?
        There is no clear answer on resource consumption between dynamically generated controls and drag-and-drop controls before writing. It depends on the specific implementation method and usage scenarios.
        Dynamically generated controls are usually created dynamically according to requirements at runtime, so that controls can be flexibly generated according to actual needs and avoid unnecessary waste of resources. However, dynamically generating controls requires additional calculations and memory allocation at runtime, which may increase some overhead.
        Drag-and-drop controls before writing are usually done through a visual editor during design. Drag-and-drop and layout can be done directly on the interface, which is relatively more intuitive and convenient. However, drag-and-drop controls before writing may take up certain resources during design, especially for complex interfaces and a large number of controls.
        Therefore, which method to choose needs to be decided based on specific needs and scenarios. If the interface is relatively simple, the number of controls is limited, and the controls need to be dynamically changed frequently, dynamically generated controls may be more resource-saving. If the interface is complex, the number of controls is large and fixed, and there is no need to frequently change the controls, it may be more convenient and resource-saving to drag and drop the controls before writing.

    4. A BackgroundWorker can only start RunAsync once at the same time?
        Yes, a BackgroundWorker can only start RunAsync once at the same time. BackgroundWorker is a component for executing long-running tasks on a background thread. It provides a simple way to perform asynchronous operations and return results upon completion.
        When the RunAsync method of BackgroundWorker is called, it performs the specified operation in the background thread. The RunAsync method cannot be called again until the operation is complete. If you try to call the RunAsync method again, an InvalidOperationException exception will be thrown.
        If you need to perform multiple asynchronous operations at the same time, you can consider using the Task class or other multi-threading mechanism to implement it. The Task class provides a more flexible and powerful asynchronous programming model that can start and manage multiple tasks at the same time.
    
    5. In what thread are the events of BackgroundWorker executed?
        The DoWork event handler is executed in a background thread and is used to handle time-consuming operations. This allows the main thread to remain responsive and not blocked.
        
        ProgressChanged and RunWorkerCompleted in the BackgroundWorker class are initiated and processed by the main thread.
        
        The ProgressChanged event is used to report progress updates,
        the RunWorkerCompleted event is triggered after the background operation is completed,
        the ReportProgress method is used to report progress in DoWork,
        and the CancelAsync method is used to request a cancellation operation.
        
        The eportProgress method is initiated by the background thread in the DoWork method. It is used to report progress information to the main thread.

    6. Foreground thread, background thread, main thread, child thread, synchronous thread, asynchronous thread. The
        foreground thread refers to a thread that blocks the application from closing. It will wait for all foreground threads to finish executing before terminating the application. In C#, threads created by the Thread class are foreground threads by default.
        A background thread is a thread that executes in the background, as opposed to the main thread (the foreground thread). Background threads will not prevent the application from exiting. When all foreground threads end, the background threads will automatically terminate. Background threads are usually used to perform tasks that do not require interaction with the user interface, such as performing time-consuming calculations, file operations, network requests, etc. They can be executed silently in the background of the application without blocking the user interface's responsiveness.
        The main thread generally refers to the calling thread, that is, the thread that runs at the beginning, such as the UI thread of form1, or the Main() of the console. The sub-thread is relative to the main thread. Another thread started by the main thread is generally called a sub-thread. (Father begets son).
        
        The difference between asynchronous threads and synchronous threads is the relationship between threads and how they execute. Asynchronous threads run independently and execute in parallel with each other, while synchronous threads need to cooperate with other threads to wait for each other or execute synchronously.
        Asynchronous threads refer to threads that execute simultaneously in an application. They can execute in parallel with the current thread, run independently of each other, and their execution order and completion time are not affected by the current thread. Asynchronous threads are often used to perform time-consuming operations to avoid blocking the current thread.

        Synchronous threads refer to threads that execute in a certain order. They need to cooperate with the current thread to wait for each other or execute synchronously. Synchronized threads are often used to ensure thread safety or ensure the orderly execution of tasks.

        The difference between asynchronous and synchronous is the relationship between threads and how they execute:

        Asynchronous threads run independently without interfering with each other. They can execute in parallel without waiting for the completion of other threads.
        Synchronous threads need to cooperate with other threads, which may wait for each other or execute synchronously to ensure orderly execution of tasks or thread safety.
        Asynchronous threads are often used to perform time-consuming operations to avoid blocking the current thread and improve application responsiveness.
        Synchronized threads are often used to ensure thread safety and ensure that multiple threads will not conflict in accessing shared resources.

        Thread can be used to create a foreground thread or a background thread, and its behavior depends on how the thread is created and the context in which it exists. The Thread used in Task is a background thread, which executes asynchronously and does not block the main thread. The Thread used in the UI main thread is a foreground thread. If the main thread is blocked, the interface will become stuck or unresponsive.
        
        The Thread used in Task is a background thread that executes asynchronously. In this case, Task creates a new thread to perform the asynchronous operation, and the main thread can continue to perform other tasks. This background thread is independent from the main thread and will not block the execution of the main thread.

        The Thread used in the UI main thread is a foreground thread, which blocks the execution of the main thread. In UI applications, the main thread is usually the thread used to process the user interface. If time-consuming operations are performed in the main thread, the interface will become stuck or unresponsive. Therefore, in order to maintain the smoothness of the user interface, time-consuming operations are usually executed in background threads.

        Note that if you use the Thread.Join() method in the UI main thread to wait for the execution of the synchronization thread, the main thread will be blocked until the synchronization thread completes execution. In this case, the synchronization thread blocks the current thread, making the current thread a synchronization thread.
        
        The child thread in BackgroundWorker is the background thread. A background thread is a thread that executes in the background while the application is running. It executes in parallel with the main thread and does not block the execution of the main thread.
        The child thread created by BackgroundWorker is a background thread by default, which performs long-running operations in the background without blocking the main thread. This allows the main thread to continue responding to user interface interactions without suspended animation.
        To summarize, background threads are an implementation of asynchronous threads that can perform long-running operations in the background without blocking the execution of the main thread. Asynchronous threads can be background threads or foreground threads, and background threads are a specific type of asynchronous threads.
        
    7. Why do we often talk about asynchronous operations but not asynchronous threads?
        In order to make programming simpler, we deliberately avoid using the concepts of underlying thread pools or asynchronous threads, and use the concept of higher-level abstract encapsulation. Therefore, we talk about asynchronous operations, not asynchronous threads.
        Task is a high-level encapsulation of asynchronous operations. It provides a higher-level programming model, making asynchronous programming simpler and easier to understand. By using Task, we can abstract and encapsulate the execution process and results of asynchronous operations without directly operating threads.

        Task is designed to make it easier for developers to write asynchronous code without paying too much attention to the details of the underlying thread. It provides a series of methods and properties for managing the status of asynchronous operations, handling exceptions, obtaining results, etc. Developers can write and manage the execution logic of asynchronous operations by using these methods and properties.

        By using Tasks, developers can decompose complex asynchronous operations into multiple small tasks, and organize and manage these tasks through dependencies between tasks. This can make asynchronous programming more intuitive and easy to understand, and avoid the complexity and trouble caused by directly operating threads.

        Therefore, using Tasks makes it easier for developers to get started and use asynchronous programming without having to delve into the details and complexities of underlying threads. It provides a higher-level abstraction and concepts that make asynchronous programming easier to understand and use.

2. BackgoundWorker instance


    1. A backgroundworker control, button, textbox, label. The interface is as follows :
        

        
        Program:

        private void BtnRun_Click(object sender, EventArgs e)
        {
            backgroundWorker1.WorkerReportsProgress = true;//要显示进度
            label1.BackColor = Color.Transparent;
            label1.Text = "0";
            backgroundWorker1.RunWorkerAsync();
            // backgroundWorker1.RunWorkerAsync("Hello world");//a
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)//子线程
        {
            //string s = e.Argument as string;//b
            for (int i = 0; i < 101; i++)
            {
                Thread.Sleep(100);
                backgroundWorker1.ReportProgress(i);//c
                ShowMsg(i.ToString());
                //ShowMsg(i.ToString()+s );//d
            }
            e.Result = "线程中的信息";//e
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)//主线程
        {
            progressBar1.Value = e.ProgressPercentage;//f
            label1.Text = e.ProgressPercentage.ToString();
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)//主线程
        {
            ShowMsg("程序执行完成。");
            ShowMsg(e.Result.ToString());//g
        }

        private void ShowMsg(string s)
        {
            if (TxtInfo.InvokeRequired)
            { BeginInvoke(new Action(() => { TxtInfo.AppendText($"{s} \r\n"); })); }
            else
            { TxtInfo.AppendText($"{s} \r\n"); }
        }


        
    2. RunWorkerAsync() is to start the sub-thread. You can bring parameters as shown in a. The
        parameters are passed in the sub-thread through DoWorkEventArgs e, converted with e.Argument, and transformed at b, including passing parameters in the form of an array.
        Receive data at d, or process data.
    
    3. Report progress at point c.
        The progressPercentage parameter of the ReportProgress method should be an integer value between 0 and 100 representing the percentage of progress. For example, you can report to the ProgressChanged event handler that the task is halfway complete by calling backgroundWorker1.ReportProgress(50).
        Calling the ReportProgress method from the DoWork event handler passes updated progress information to the ProgressChanged event handler. You can then update the progress bar or perform other operations in the ProgressChanged event handler to reflect the progress of the operation.
        The data is sent out at c, received in ProgressChangedEventArgs e of the ProgressChanged event, and the data (object) is extracted through e.ProgressPercentage at f.
        
    4. The Result attribute at e is a temporary storage warehouse , which is equivalent to a public variable. The value in the sub-thread is passed to the main thread, such as g, and can also be passed in the ProgressChanged event.
        
        
    5. In short: If it is not necessary, try not to use the old method of backgroundworker.
 

Guess you like

Origin blog.csdn.net/dzweather/article/details/132687753