Reputation: 890
When I use a message box to trace where program stop
at com.CommandText
it shows nothing and the application hangs (freezes).
The same function works perfectly if I use it without a Thread
.
What is the reason for this?
public bool load_complete=false;
private void button7_Click(object sender, EventArgs e)
{
Thread t1 = new Thread(new ThreadStart(load_data));
t1.Start();
Thread.Sleep(2000);
while (load_complete == false) ;
t1.Abort();
}
public void load_data()
{
string connectionString = @"Data Source=(LocalDB)\v11.0;AttachDbFilename=" + Application.StartupPath + "\\Database1.mdf;Integrated Security=True;";
SqlConnection conn = new SqlConnection(connectionString);
conn.Open();
MessageBox.Show("open");
SqlCommand com = new SqlCommand();
try
{
com.Connection = conn;
DataSet ds = new DataSet();
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter();
com.CommandText = "select username,password from login where username ='" + textBox1.Text + "'";
da.SelectCommand = com;
da.Fill(dt);
dataGridView1.DataSource = dt;
username = (string)this.dataGridView1.Rows[0].Cells[0].Value;
pass = (string)this.dataGridView1.Rows[0].Cells[1].Value;
load_complete = true;
}
catch (Exception ex){
MessageBox.Show(ex.Message);
}
}
Upvotes: 0
Views: 46
Reputation: 2840
Another option is to use a BackgroundWorker, which as it says, uses a background thread that won't tie up your main UI thread. It already comes with events for when the process completes.
You just drag a BackgroundWorker from the Toolbox to your form.
Note:In your LoadData method, you can't access any form elements, so you'd have to take the MessageBox out. You can refer to form elements in your BackgroundWorker completed event handler.
private void button7_Click(object sender, EventArgs e)
{
MyWorker.RunWorkerAsync();
}
private void MyWorker_DoWork(object sender, DoWorkEventArgs e)
{
LoadData();
}
private void MyWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error == null)
{
string username = (string)this.dataGridView1.Rows[0].Cells[0].Value;
string pass = (string)this.dataGridView1.Rows[0].Cells[1].Value;
}
else
{
MessageBox.Show("Houston we have a problem");
}
}
private void LoadData()
{
// Load your datagridview
}
Upvotes: 1
Reputation: 1732
Short version: You are blocking UI thread which would handle display of your message box, dont block UI thread
Longer version:
There a number of problems with your code listed above. Let's start with the obvious:
1.
public bool load_complete=false;
...
while (load_complete == false) ;
your flag
is not marked with volatile and compiler optimizations may assume access by a single thread, in which case your code would stuck in UI forever. I'd suggest using volatile here if it were not for many other problems in the code...
2.
Thread.Sleep(2000);
You are blocking UI thread and thus any user interaction for 2+ seconds, this is a big taboo from CS101 and onwards, please consider using Tasks and async/await here to keep UI uninterruptible. Minimal changes to your code that would still use SqlDataAdapter would require:
a) marking button handler async and awaiting for whatever you need:
private async void button7_Click(object sender, EventArgs e)
{
await load_data();
// more UI code is free to go here
}
b) running load_data
asynchronously on a thread pool and returning a Task object to caller:
public Task load_data()
{
return Task.Run( () =>
{
// paste your old load_data code here verbatim
});
}
3.
t1.Abort();
Can't imagine what that thread did to you so you want to interrupt it in cold blood. Thread would terminate when it reaches the end of the function that you passed in, absolutely no need to do manual abortion here, if it happens that you need to wait for a thread next time, please consider Join method
Upvotes: 3