Reputation: 491
I don't think the following question is rarely seen. But since I don't know how to search for the right answer, so I'm still stuck on it.
I have a label in the form and I want to show something before another job is invoked:
private void btnLoadEvent_Click(object sender, EventArgs e)
{
lbStatus.Text = "Loading... ";
load();
}
private void load()
{
Thread.Sleep(5000);
lbStatus.Text = "Done";
}
The label won't show anything before load() is complete.
Then I changed my program usnig async/await:
private async void btnLoadEvent_Click(object sender, EventArgs e)
{
lbStatus.Text = "Loading... ";
await load();
}
private async Task load()
{
Thread.Sleep(5000);
lbStatus.Text = "Done";
}
It doesn't change anything. Does anyone have any idea?
2014/4/3:
As a note, I think I've figured out how async/await works. And to avoid misleading any possible reader, I list my final solution as follows:
private async void btnLoadEvent_Click(object sender, EventArgs e)
{
lbStatus.Text = "Loading... ";
string content = await loadAsync();
}
private async Task<string> loadAsync()
{
using (WebClient webClient = new WebClient())
{
string json = await webClient.DownloadStringTaskAsync(
"http://api.openweathermap.org/data/2.5/weather?q=Taipei,tw");
lbStatus.Text = "Done";
return json;
}
}
In practice, to meet the Decoupling Principle, "lbStatus.Text = ... " could be better moved from loadAsync() to btnLoadEvent_Click() although it works fine.
And thanks everyone who helped.
Upvotes: 2
Views: 6180
Reputation: 1432
You need to use BackgroundWorker. Something like that.
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "Loading";
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
load();
}
private void load()
{
System.Threading.Thread.Sleep(1000);
if(InvokeRequired)
this.Invoke(new Action(()=>label1.Text = "Done"));
}
Upvotes: 0
Reputation: 120380
You didn't really go async. Thread.Sleep is blocking and because your async function never yields it will still block the call site. Use await Task.Delay(...
instead.
private void btnLoadEvent_Click(object sender, EventArgs e)
{
lbStatus.Text = "Loading... ";
load();
}
private async Task load()
{
await Task.Delay(5000);
lbStatus.Text = "Done";
}
Upvotes: 3
Reputation: 7
Try using a BackgroundWorker . Set your label.Text to Loading before executing the BackgroundWorker's RunWorkerAsync
method. Do your stuff (like your Thread.Sleep(5000)) in the Do_Work
event and change the status of your label in the RunWorkerCompleted
event. Visit this link to see an example.
Upvotes: 0