Today I’ll show you how to fix cross-thread problem with the second way. This way is used with Invoke and BeginInvoke API. What is Invoke and BeginInvoke? let’s read below topics
First Let’s understanding the Thread and MultiThread and synchronous and asynchronous
Read here
What is Single Thread and MultiThread
Single Thread:
If we have couple of tasks to be worked on and the current system provides a single thread which can work all those, then it takes one by one and process as
Multi-Thread:
Synchronous Single Threaded
Synchronous Multi-Threaded
Asynchronous Single Threaded
Asynchronous Multi-Threaded
What is Synchronous and Asynchronous
Synchronous
Example:
1. You are in a queue to get a movie ticket. You cannot get one until everybody in front of you gets one and the same applies to the people queued behind you
2. Ammunition in the gun: shot every ammunition one by one
Asynchronous
Example:
1. You are in restaurant with many other people. You order your food. Other people can also order their food. They don’t have to wait for your food to be cooked and served to you before they can order. In the kitchen, workers are continuously cooking, serving and taking orders. People will get their food servered as soon as it is cooked
2. About car traffic: the car can pass another car, no need to waiting the before car
———————————————
Threading is about workers; Asynchrony is about tasks.
Resource contention
– C# cung cấp 1 giải pháp an toàn hơn đó là Invoke. Khi bạn gọi phương thức này của một form (hoặc control) từ 1 thread khác, form (control) đó sẽ bị lock, chỉ cho phép thread đã gọi nó truy cập. Khi thread này hoàn thành tác vụ của nó, form (control) lại được giải phóng cho thread khác gọi. Như vậy, các thread sẽ được đồng bộ với nhau và chương trình của bạn sẽ ko bị crash. Đó gọi là thread-safe.
– Có những control ko yêu cầu Invoke để thực hiện thread-safe. Nghĩa là nó có thể được truy cập một cách trực tiếp không qua Invoke. Thuộc tính InvokeRequired sẽ cho biết một control có yêu cầu Invoke khi gọi hay không?
BeginInvoke and Invoke
BeginInvoke() will schedule the asynchronous action on the GUI thread. When the asynchronous action is scheduled, your code continues. Some time later (you don’t know exactly when) your asynchronous action will be executed
Invoke() will execute your asynchronous action (on the GUI thread) and wait until your action has completed. -> easy get deadlock but safe than BeginInvoke
Look at the below example:
Source code
Main.cs
private bool isProcessRunning = false;
private void Demo(object sender, EventArgs e)
{
listBox1.Items.Clear();
// If a process is already running, warn the user and cancel the operation
if (isProcessRunning)
{
MessageBox.Show("A process is already running.");
return;
}
// Initialize the thread that will handle the background process
Thread backgroundThread = new Thread(new ThreadStart(() => CallingThread()));
// Start the background process thread
backgroundThread.Start();
}
1st Example:
single code:
listBox1.Invoke(new Action(() => listBox1.Items.Add(lst[i])));
multi code: use { and }
listBox1.BeginInvoke(new Action(() =>
{
listBox1.Items.Add(lst[i]))
});
We use Invoke in this case because we want to wait until the user action has completed.
// Developer: zidane / VịLH (huuvi168@gmail.com)
// Last modified: 2016-07-07
private void CallingThread()
{
toolStripProgressBar.ProgressBar.Invoke(new Action(() =>
toolStripProgressBar.Style = ProgressBarStyle.Marquee));
toolStripStatusLabel.Text = "Waiting for task ...";
// Set the flag that indicates if a process is currently running
isProcessRunning = true;
clsDBConnect clsDB = new clsDBConnect();
List<string> lst = clsDB.SelectQueryString();
// Thread.sleep(100); // remember set Thread.Sleep(1000) here
for (int i = 0; i < lst.Count; i++)
{
if (listBox1.InvokeRequired)
listBox1.Invoke(new Action(() => listBox1.Items.Add(lst[i])));
}
// Show a dialog box that confirms the process has completed
toolStripStatusLabel.Text = "Done";
// Reset the progress bar's value if it is still valid to do so
toolStripProgressBar.ProgressBar.Invoke(new Action(() =>
toolStripProgressBar.Style = ProgressBarStyle.Continuous));
// Reset the flag that indicates if a process is currently running
isProcessRunning = false;
}
2nd Example:
listBox1.BeginInvoke(new Action(() => listBox1.Items.Add(lst[i])));
Shouldn’t use beginInvoke in this case, because it will crashed your program.
private void CallingThread()
{
toolStripProgressBar.ProgressBar.Invoke(new Action(() =>
toolStripProgressBar.Style = ProgressBarStyle.Marquee));
toolStripStatusLabel.Text = "Waiting for task ...";
// Set the flag that indicates if a process is currently running
isProcessRunning = true;
clsDBConnect clsDB = new clsDBConnect();
List<string> lst = clsDB.SelectQueryString();
for (int i = 0; i < lst.Count; i++)
{
if (listBox1.InvokeRequired)
listBox1.BeginInvoke(new Action(() => listBox1.Items.Add(lst[i])));
}
// Show a dialog box that confirms the process has completed
toolStripStatusLabel.Text = "Done";
// Reset the progress bar's value if it is still valid to do so
toolStripProgressBar.ProgressBar.Invoke(new Action(() =>
toolStripProgressBar.Style = ProgressBarStyle.Continuous));
// Reset the flag that indicates if a process is currently running
isProcessRunning = false;
}
Relative topic
http://learn-tech-tips.blogspot.com/2015/11/how-to-fix-cross-thread-problem-CSharp.html
If you have any feedback, leave your comment, we can discuss about it!
Have a nice day!
Zidane
https://learn-tech-tips.blogspot.com/