【问题标题】:BackgroundWorker with Webclient downloadstringBackgroundWorker 与 Webclient 下载字符串
【发布时间】:2013-05-23 19:13:37
【问题描述】:

所以基本上我想在互联网上检索 .txt 文件的内容并将其写入 a 标签。但是,虽然这样做,Windows 窗体会冻结。

所以我想把它放到BackgroundWorker中。还有一个进度条,应该在进度期间填充。我的代码如下所示:

private void RetrieveTxt(string currentversion)
    {
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    }

void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        WebClient wc = new WebClient();
        label1.Text = wc.DownloadString("http://example.org/version.txt");
    }

void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        updateProgress.Value = e.ProgressPercentage;
    }

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        updateProgress.Visible = false;
    }

但是,它不起作用;标签永远不会更新,进度条保持空白。

感谢您的帮助,谢谢! :)

【问题讨论】:

  • 如果你在 .Net 4.5 上,你可以使用 async/await
  • 如果你使用的是 BackgroundWorker,你需要这样做:worker.RunWorkerAsync();
  • 并且...记住不要修改 DoWork 代码中的任何 UI 对象,否则您将收到一个很好的异常。为此,您拥有ProgressChanged

标签: c# backgroundworker webclient downloadstring


【解决方案1】:

如果您使用的是 C# 5.0,您可以执行以下操作:

label1.Text = await client.DownloadStringTaskAsync("http://example.org/version.txt");

就是这么简单。

如果您不是,那么您可以利用 WebClient 的异步支持;你不需要使用 BackgroundWorker:

WebClient client = new WebClient();
client.DownloadStringCompleted += (s, data) =>
{
    label1.Invoke(new Action(() => label1.Text = data.Result));
};
client.DownloadStringAsync(new Uri("http://example.org/version.txt"));

至于为什么你的代码不起作用:

  1. 您从未真正启动过工作程序。你从来没有打电话给worker.RunWorkerAsync();
  2. 您正在从后台任务访问 UI 控件,因此当您尝试从 DoWork 处理程序访问标签时它会中断。您需要将结果设置为 WebClient 返回的字符串,然后在完成的处理程序中设置标签。

【讨论】:

  • 非常感谢您非常详细的回答!今天学到了一些新东西:)
【解决方案2】:

您需要一个委托,因为后台线程无法对 UI 控件进行操作:

private delegate void InvokeUpdateText(String theText);
private void UpdateText(String theText)
{
    if (InvokeRequired)
    {
        try { Invoke(new InvokeUpdateText(UpdateText), theText); }
        catch { }
        return;
    }
    label1.Text = theText;
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    WebClient wc = new WebClient();
    UpdateText("http://example.org/version.txt");
}

【讨论】:

  • 使用 BGW 的整个 要点 是您不需要 需要这样做。您可以只设置结果,然后在完成的处理程序中修改 UI,该处理程序在 UI 线程中运行。此外,空的 catch all 块是一件 可怕 的事情。不要那样做。
  • 首先,认为后台工作人员会以某种方式使您免于不正确地访问 UI 元素是错误的。其次,没有什么可以从 Invoke 中的特定错误处理中收集到。如果你想抓住它,但你会用它做什么?最好将这个包罗万象用作最后的手段……无论如何,用户界面都应该使用它们,这成为一个有争议的问题。
  • 您不知道如何处理异常这一事实正是您不应该捕获它的原因。只有当你确实知道如何处理它时,你才应该捕获一个异常。我从来没有说过 BGW 可以让你避免所有错误,我说它的目的是简化与 UI 同步长时间运行的任务。您正在使用 BGW 并没有利用它为此目的提供的任何功能。如果你不打算用它来完成它的工作,为什么还要使用它呢?
猜你喜欢
  • 2014-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-18
  • 1970-01-01
  • 1970-01-01
  • 2015-02-20
相关资源
最近更新 更多