In C# application development, we often separate UI threads and worker threads to prevent the interface from stopping response. At the same time, we need to update the controls on the UI interface in the worker thread. However, direct access will cause "invalid inter-thread operations" because .NET prohibits cross-thread calls to controls, otherwise anyone can operate the controls, which may eventually cause errors. The following are several methods of cross-thread access:
1. Prohibit checking cross-thread access (this method is not recommended)
This method does not check cross-thread access, allowing each thread to operate UI elements, and is prone to errors.
public Form2() { InitializeComponent(); //Confirm cross-thread access checks (this method is not recommended) = false; }
2. Use the delegate method to delegate it to the UI control to update
//Use the delegate method to delegate it to the UI control to updateprivate void button1_Click(object sender, EventArgs e) { Thread thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel2)); ("Update Label"); } private void UpdateLabel2(object str) { if () { // When the InvokeRequired property value of a control is true, it means that there is a thread other than creating it that wants to access it Action<string> actionDelegate = (x) => { this. = (); }; // or // Action<string> actionDelegate = delegate(string txt) { this. = txt; }; this.(actionDelegate, str); } else { this. = (); } }
3. Use delegate and BeginInvoke to control controls from other threads
Just change the Invoke in this.(actionDelegate, str); above to the BeginInvoke method.
The difference between the Invoke method and the BeginInvoke method is: the Invoke method is synchronous, it will wait for the worker thread to complete, and the BeginInvoke method is asynchronous, it will start another thread to complete the work line.
4. Use the synchronization context: SynchronizationContext method
This method is to obtain the context information of the main thread, and then push the access UI control method to the message queue of the UI context in the child thread, using POST or Send;
private SynchronizationContext synchronizationContext; private void button2_Click(object sender, EventArgs e) { synchronizationContext = ; new Thread(() => { UpdateText("Cross-thread access"); }).Start(); } void UpdateText(string msg) { (_ => this. = msg, null); }
5. Use BackgroundWorker component (this method is recommended)
BackgroundWorker is a control used in .NET to perform multi-threaded tasks. It allows programmers to perform some operations on a separate thread. Time-consuming operations (such as downloads and database transactions).
public partial class FileManagerForm : Form { FileInfo file ; BackgroundWorker bw; ServerFile server; public FileManagerForm(string filePath) { InitializeComponent(); file = new FileInfo(filePath); long size = / 1024 / 1024; = (int)size+ "MB"; bw = new BackgroundWorker(); server = new ServerFile(); } private void FileManagerForm_Load(object sender, EventArgs e) { = 0; = 100; = true; = true; += Bw_DoWork; += Bw_ProgressChanged; += Bw_RunWorkerCompleted; (); } private void Bw_DoWork(object sender, DoWorkEventArgs e) { using(FileStream fileRead= ()) { long setp = / 100; while ( > ) { if () { break; } byte[] bytes = new byte[1024]; int count = (bytes, 0, ); long writeLength= (bytes, count); if(writeLength >* setp) { int size = (int)(writeLength / 1024 / 1024); ( + 1, size); } } (); } } private void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e) { = > ?:; = () + "MB"; } private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if ( == ) { ("The file was sent successfully!"); } else { ("File sending failed!"); } (); } private void btnCancel_Click(object sender, EventArgs e) { (); } }
The above is the detailed content of how to access UI elements across threads in Winform. For more information about Winform accessing UI elements, please follow my other related articles!