C # across threads update the appropriate handling UI interface mechanism to explore a friendly exit interface (transfer)

This paper mainly talk about the case of a program in C # form a frequently encountered, that is, when the form of the exit, exit exception occurred.

Contact the author plus group and mode (activation issue in the group): http://www.hslcommunication.cn/Cooperation 

Welcome to explore technology

 

Let's look at a typical scenario, the timing of obtaining data from PLC or remote server, and then update the interface tag, basically updated in real time. We can model simplification, reduced to a form inside a form, open thread regularly read

    the Form1 partial class public: Form1 
    { 
        public the Form1 () 
        { 
            the InitializeComponent (); 
        } 

        Private void the Form1_Load (SENDER Object, EventArgs E) 
        { 
            Thread the System.Threading.Thread new new = (new new System.Threading.ThreadStart (ThreadCapture)); 
            Thread. = to true IsBackground; 
            Thread.Start (); 
        } 

        Private void ThreadCapture () 
        { 
            System.Threading.Thread.Sleep (200 is); 
            the while (to true) 
            { 
                // we assume that data is retrieved from the remote server or to the PLC, because it may be time-consuming, we get on a background thread, and the state has been running 
                // we also assume that the data acquisition frequency is 200ms once, then the data out 
                int data = random.Next (1000);

                Next is the cross-thread // display 
                the Invoke (the Action new new (() => 
                 { 
                     Label1.Text data.ToString = (); 
                 })); 


                System.Threading.Thread.Sleep (200 is); 
            } 
        } 

        Private the System.Threading Thread .thread; 
        Private the Random Random new new = the Random (); 
    } 
}  

So we are likely to write, when we click on the window, the following exceptions occur

 

Send the root cause of the problem is that when you click on a form is closed, the form of all the components begin to release resources, but the thread has not shut down immediately, so the appeal against the code, we be optimized.

 

 

 

1. Optimize constantly create delegate instances


 

        void ThreadCapture Private () 
        { 
            the showInfo the Action new new = <String> (m => 
            { 
                Label1.Text = m; 
            }); 
            System.Threading.Thread.Sleep (200 is); 
            the while (to true) 
            { 
                // We assume that the data is obtained from the PLC or remote server, as may be more time-consuming, we get on a background thread, and the state has been running 
                // we also assume that the data acquisition frequency is 200ms once, and then the data is displayed 
                int data Random.Next = (1000); 

                // Next is a cross-thread of 
                the Invoke (the showInfo, data.ToString ()); 


                System.Threading.Thread.Sleep (200 is); 
            } 
        } 

        Private the Action <String> the showInfo;
        private System.Threading.Thread thread;
        private Random random = new Random( );

 

 This will avoid the frequent create a delegate instance every 200ms, these examples have to take up commission in the GC memory consumption data recovery, users just do not feel it, but the development of good habits to use less memory, to perform a lot of things.

 I just started thinking about when to exit if you avoid the exception, since it is an error is empty, I added a judge chant

        void ThreadCapture Private () 
        { 
            the showInfo the Action new new = <String> (m => 
            { 
                Label1.Text = m; 
            }); 
            System.Threading.Thread.Sleep (200 is); 
            the while (to true) 
            { 
                // We assume that the data is obtained from the PLC or remote server, as may be more time-consuming, we get on a background thread, and the state has been running 
                // we also assume that the data acquisition frequency is 200ms once, and then the data is displayed 
                int data Random.Next = (1000); 

                // display followed by cross-thread 
                IF the Invoke (the showInfo, data.ToString ()) (IsHandleCreated IsDisposed &&!); 


                System.Threading.Thread.Sleep (200 is); 
            } 
        }

  

Display interface when the handle is created under the judgment, whether the current is released. Abnormal less frequency, but still out. The following provides a simple and crude way of thinking, since the error has been released, I'll catch the exception

        void ThreadCapture Private () 
        { 
            the showInfo the Action new new = <String> (m => 
            { 
                Label1.Text = m; 
            }); 
            System.Threading.Thread.Sleep (200 is); 
            the while (to true) 
            { 
                // We assume that the data is obtained from the PLC or remote server, as may be more time-consuming, we get on a background thread, and the state has been running 
                // we also assume that the data acquisition frequency is 200ms once, and then the data is displayed 
                int data Random.Next = (1000); 

                the try 
                { 
                    // Next is displayed across threads 
                    IF the Invoke (the showInfo, data.ToString ()) (IsHandleCreated IsDisposed &&!); 
                } 
                the catch (ObjectDisposedException)
                {
                    break;
                }
                catch
                {
                    throw;
                }


                System.Threading.Thread.Sleep( 200 );
            }
        }

  

Like this simply brutal resolved, but still feel very good, so do not use try..catch, a change in thinking, I add a flag indicating whether the form is displayed. When the form is closed, the reset flag

        void ThreadCapture Private () 
        { 
            the showInfo the Action new new = <String> (m => 
            { 
                Label1.Text = m; 
            }); 
            isWindowShow = to true; 

            System.Threading.Thread.Sleep (200 is); 
            the while (to true) 
            { 
                // We Assuming that the data is retrieved from the PLC or remote server, as may be more time-consuming, we get on a background thread, and the state has been running 
                // we also assume that the frequency is 200ms access to data once, and then the data displayed 
                int = Random.Next Data (1000); 

                // Next, the thread is a cross- 
                IF (isWindowShow) the Invoke (the showInfo, data.ToString ()); 
                the else BREAK;


                System.Threading.Thread.Sleep( 200 );
            }
        }

        private bool isWindowShow = false;
        private Action<string> showInfo;
        private System.Threading.Thread thread;
        private Random random = new Random( );

        private void Form1_FormClosing( object sender, FormClosingEventArgs e )
        {
            isWindowShow = false;
        }

The whole process become like this, when we repeatedly test test again, still often out, this time we need to consider the deeper things, I quit the program needs to be done? The acquisition thread off, stop refreshing, this time to really exit.

This time you need synchronous technology, we continue to transform

 

        void ThreadCapture Private () 
        { 
            the showInfo the Action new new = <String> (m => 
            { 
                Label1.Text = m; 
            }); 
            isWindowShow = to true; 

            System.Threading.Thread.Sleep (200 is); 
            the while (to true) 
            { 
                // We Assuming that the data is retrieved from the PLC or remote server, as may be more time-consuming, we get on a background thread, and the state has been running 
                // we also assume that the frequency is 200ms access to data once, and then the data displayed 
                int = Random.Next Data (1000); 

                // display followed by cross-thread, and detects whether the form is closed 
                iF (isWindowShow) the Invoke (the showInfo, data.ToString ()); 
                the else BREAK;


                System.Threading.Thread.Sleep (200 is); 
                // Close again detected whether the form 
                IF BREAK (isWindowShow!); 
            } 

            // notifies the host interface is ready to exit 
            resetEvent.Set (); 
        } 

        Private System.Threading.AutoResetEvent ResetEvent = System.Threading.AutoResetEvent new new (to false); 
        Private = BOOL isWindowShow to false; 
        Private the Action <String> the showInfo; 
        Private the System.Threading.Thread Thread; 
        Private the Random Random new new = the Random (); 

        Private void Form1_FormClosing (Object SENDER, FormClosingEventArgs E) 
        { 
            isWindowShow = to false;
            resetEvent.WaitOne (); 
        } 
    }

According to the idea we write this code. Running about the results stuck no more, just click on the Analysis of the reason is the time to exit, if the Invoke found when displayed, will form a deadlock, it is a way, changed under the following mechanisms

        void ThreadCapture Private () 
        { 
            the showInfo the Action new new = <String> (m => 
            { 
                Label1.Text = m; 
            }); 
            isWindowShow = to true; 

            System.Threading.Thread.Sleep (200 is); 
            the while (to true) 
            { 
                // We Assuming that the data is retrieved from the PLC or remote server, as may be more time-consuming, we get on a background thread, and the state has been running 
                // we also assume that the frequency is 200ms access to data once, and then the data displayed 
                int = Random.Next Data (1000); 

                // display followed by cross-thread, and detects whether the form is closed 
                iF (isWindowShow) BeginInvoke (the showInfo, data.ToString ()); 
                the else BREAK;


                System.Threading.Thread.Sleep (200 is); 
                // Close again detected whether the form 
                IF BREAK (isWindowShow!); 
            } 

            // notifies the host interface is ready to exit 
            resetEvent.Set (); 
        } 

        Private System.Threading.AutoResetEvent ResetEvent = System.Threading.AutoResetEvent new new (to false); 
        Private = BOOL isWindowShow to false; 
        Private the Action <String> the showInfo; 
        Private the System.Threading.Thread Thread; 
        Private the Random Random new new = the Random (); 

        Private void Form1_FormClosing (Object SENDER, FormClosingEventArgs E) 
        { 
            isWindowShow = to false;
            resetEvent.WaitOne (); 
        }

Invoke mechanism into asynchronous time, we can solve this problem, but BeginInvoke method is not particularly secure manner, and we withdraw when there may be a card that will be, we need to think there is no better mechanism.

 

If we do withdraw from the window of a waiting would be better? Neither card out of the main window, and can be the perfect exit, we create a small window

 

Get rid of the border, the interface is so simple, then transform the code

 

 

 

    public partial class FormQuit : Form
    {
        public FormQuit( Action action )
        {
            InitializeComponent( );
            this.action = action;
        }

        private void FormQuit_Load( object sender, EventArgs e )
        {

        }

        // 退出前的操作
        private Action action;

        private void FormQuit_Shown( object sender, EventArgs e )
        {
            // 调用操作
            action.Invoke( );
            Close( );
        }
    }

 

 We just put this operation before the exit to the exit window which can

        void ThreadCapture Private () 
        { 
            the showInfo the Action new new = <String> (m => 
            { 
                Label1.Text = m; 
            }); 
            isWindowShow = to true; 

            System.Threading.Thread.Sleep (200 is); 
            the while (to true) 
            { 
                // We Assuming that the data is retrieved from the PLC or remote server, as may be more time-consuming, we get on a background thread, and the state has been running 
                // we also assume that the frequency is 200ms access to data once, and then the data displayed 
                int = Random.Next Data (1000); 

                // display followed by cross-thread, and detects whether the form is closed 
                iF (isWindowShow) the Invoke (the showInfo, data.ToString ()); 
                the else BREAK;


                System.Threading.Thread.Sleep (200 is); 
                // Close again detected whether the form 
                IF BREAK (isWindowShow!); 
            } 

            // notifies the host interface is ready to exit 
            resetEvent.Set (); 
        } 

        Private System.Threading.AutoResetEvent ResetEvent = System.Threading.AutoResetEvent new new (to false); 
        Private = BOOL isWindowShow to false; 
        Private the Action <String> the showInfo; 
        Private the System.Threading.Thread Thread; 
        Private the Random Random new new = the Random (); 

        Private void Form1_FormClosing (Object SENDER, FormClosingEventArgs E) 
        { 
            FormQuit formQuit = new new FormQuit (the Action new new (() =>
            {
                isWindowShow = false;
                resetEvent.WaitOne( );
            } ));
            formQuit.ShowDialog( );
        }
    }

 

Now that your program will no longer appear above object has been released by the abnormal exit of the form displays time to time, 0-200 milliseconds. In order to have a significant role to stay, we sleep more than 200ms, so we completed the final program, as follows:

 

    public partial class Form1 : Form
    {
        public Form1( )
        {
            InitializeComponent( );
        }

        private void Form1_Load( object sender, EventArgs e )
        {
            thread = new System.Threading.Thread( new System.Threading.ThreadStart( ThreadCapture ) );
            thread.IsBackground = true;
            thread.Start( );
        }



        private void ThreadCapture( )
        {
            showInfo = new Action<string>( m =>
            {
                label1.Text = m;
            } );
            isWindowShow = true;

            System.Threading.Thread.Sleep (200); 
            the while (to true) 
            { 
                // We assume that this data is retrieved from the PLC or remote server, as may be more time-consuming, we get on a background thread, and has been in operating state 
                // we assume that the frequency of the data acquisition time 200ms, then the data is displayed 
                int = Random.Next data (1000); 

                // display followed by cross-thread, and detects whether the form is closed 
                if (isWindowShow ) the Invoke (the showInfo, data.ToString ()); 
                the else BREAK; 


                System.Threading.Thread.Sleep (200 is); 
                // Close again detected whether the form 
                ! if (isWindowShow) {System.Threading.Thread.Sleep ( 50) ; BREAK;} 
            } 

            // notify the main interface is ready to quit 
            resetEvent.Set (); 
        }

        private System.Threading.AutoResetEvent resetEvent = new System.Threading.AutoResetEvent( false );
        private bool isWindowShow = false;
        private Action<string> showInfo;
        private System.Threading.Thread thread;
        private Random random = new Random( );

        private void Form1_FormClosing( object sender, FormClosingEventArgs e )
        {
            FormQuit formQuit = new FormQuit( new Action(()=>
            {
                System.Threading.Thread.Sleep( 200 );
                isWindowShow = false;
                resetEvent.WaitOne( );
            } ));
            formQuit.ShowDialog( );
        }
    }
https://www.cnblogs.com/dathlin/p/10147736.html

  

 

Guess you like

Origin www.cnblogs.com/xihong2014/p/12584535.html