Objective:
Use WinForm (C #) to build a user interface, a progress bar and a button to start the progress bar, stop the update when the progress is complete
Example:
650) this.width=650; "src=" Http://s4.51cto.com/wyfs02/M02/76/19/wKioL1ZKiOLAiXwDAAAv3UpvmTg539.png "title=" 2015-11-17 (1). png "alt=" Wkiol1zkiolaixwdaaav3upvmtg539.png "/>
Realize:
To set a loop in a button event, update the progress bar
private void Btnprogress_click (object sender, EventArgs e) {for (int II = 0; II <; ii++) {progressBar1.Value = II + 1; Thread.Sleep (100); } }
Question 1:
The progress bar is updated well, but the window is stuck during the update because the button event is in the window thread and execution does not respond to any other messages in the loop body
Resolution 1:
Add Application.doevents () to the loop body
private void Btnprogress_click (object sender, eventargs e) { for (int ii = 0; ii < 100; ii++) { Application.doevents (); progressBar1.Value = ii + 1; thread.sleep (; ) } }
Question 2:
This approach allows window events to share thread time resources, but individual execution fragments are still executed sequentially, with longer execution fragments having significant impact on other events.
Thread.Sleep (100) can be assumed to be a complex logic or calculation, and if sleep (100) is changed to sleep (1000) or greater, the effect of the user interface does not significantly improve on problem 1.
Resolution 2:
The introduction of additional threads, which enable the control of progress on its own, is actually a separation of the time-consuming logical or computational threads from the execution (time) resources of the user interface.
public void threadprogress () { while ( PROGRESSBAR1.VALUE&NBSP;<&NBSP;100) { progressbar1.value++; thread.sleep (; } ) } private void btnprogress_click (Object sender, eventargs e) { thread thprog = new thread (threadprogress); thprog. Start (); }
This code can be compiled, but cannot be executed, and will run into InvalidOperationException because the state update of the WinForm control can only be done within the user interface thread, which is actually the thread that created the form (and the same as the response clicked event). You can now track the solution given by the exception help document, how To:make thread-safe Calls to Windows Forms controls describes the complete problem definition and resolution.
WinForm the cross-thread update of a control to use the space itself or the Invoke method within the thread, the invoke parameter is assigned using the delegate function. The behavior of the thread needs to be modified.
public delegate void setprogress (INT&NBSP;PVV); void Guisetprogressmustininvokeoruithread (INT&NBSP;PVV) { progressBar1.Value = pvv; } void delesetprogress (INT&NBSP;PVV) { if ( progressbar1.invokerequired) { SetProgress Spself = new setprogress (GuisetprogRessmustininvokeoruithread); progressbar1.invoke (SPSELF,&NBSP;NEW&NBSP;OBJECT[]&NBSP;{&NBSP;PVV&NBSP;}); } } public Void threadprogress () { while (progressbar1.value < 100) { delesetprogress (progressbar1.value + 1); thread.sleep (; ) } }
The above code is the solution in the document disassembly method, Delesetprogress determined to be called by the external thread , it needs to put the actual update through the Invoke function back to the interface thread, The execution guisetprogressmustininvokeoruithread is performed using the delegate variable.
The explanation for invoke in the Help document is
Executes a delegate on the thread that owns the control ' s underlying window handle
This ensures execution in the interface thread, and of course the execution fragment is part of the Guisetprogressmustininvokeoruithread , separating the complex logic from the interface update implementation.
Question 3:
The above code will work fine, but when you close the window during the update process, you will encounter system.objectdisposedexception. The reason is that the user thread is still trying to update the progress bar after the window and space are freed.
Resolution 3:
Several options are available, forcing the end of the user thread before the window closes, waiting for the user to end the logic before the window closes, or more complex thread management logic.
This waits for the thread to end, the thread needs to remain in the member, and the user logic sets the flag to ensure the security of calls between threads.
private Thread thProgress = null; public void threadprogress () { ... thProgress = null; } private void formprogress_ FormClosing (object sender, formclosingeventargs e) { while (thprogress != null) { application.doevents (); thread.sleep (0); } } private void btnprogress_click ( Object sender, eventargs e) { if (thprogress == null) { thprogress = new thread (threadProgress); thprogress.start (); } }
This article is from the "Technology Change Life" blog, please be sure to keep this source http://btvnlue.blog.51cto.com/9578271/1713391
Cross-thread update of WinForm controls in C # invoke