Windows窗体应用程序中的异步显示

时间:2014-04-01 09:35:41

标签: c# winforms asynchronous async-await

我认为以下问题很少见。但由于我不知道如何寻找正确的答案,所以我仍然坚持下去。

我在表单中有一个标签,我想在调用另一个作业之前显示一些内容:

private void btnLoadEvent_Click(object sender, EventArgs e)
{
    lbStatus.Text = "Loading... ";
    load();
}
private void load() 
{ 
    Thread.Sleep(5000);
    lbStatus.Text = "Done";
}

在load()完成之前,标签不会显示任何内容。

然后我改变了程序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";
}

它不会改变任何东西。有没有人有任何想法?

2014年4月3日:

作为一个说明,我想我已经弄明白async / await是如何工作的。为了避免误导任何可能的读者,我列出了我的最终解决方案如下:

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;
    }
}

在实践中,为了满足解耦原则,“lbStatus.Text = ...”可以更好地从loadAsync()移动到btnLoadEvent_Click(),尽管它工作正常。

感谢所有帮助过的人。

3 个答案:

答案 0 :(得分:3)

你并没有真正去异步。 Thread.Sleep是阻塞的,因为你的异步函数永远不会产生它仍然会阻塞调用站点。请改用await Task.Delay(...

private void btnLoadEvent_Click(object sender, EventArgs e)
{
    lbStatus.Text = "Loading... ";
    load();
}

private async Task load()
{
    await Task.Delay(5000);
    lbStatus.Text = "Done";
}

答案 1 :(得分:0)

尝试使用BackgroundWorker。在执行BackgroundWorker的RunWorkerAsync方法之前,将label.Text设置为Loading。在Do_Work事件中处理您的内容(例如Thread.Sleep(5000))并更改RunWorkerCompleted事件中标签的状态。访问this link查看示例。

答案 2 :(得分:0)

您需要使用BackgroundWorker。这样的事情。

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"));
}