【问题标题】:BackgroundWorker alternatives for Windows FormsWindows 窗体的 BackgroundWorker 替代品
【发布时间】:2014-07-29 10:31:32
【问题描述】:

是否可以在 Windows 窗体应用程序中执行类似的操作?

我正在尝试寻找其他方法来更新 UI,而不是一直使用 BackgroundWorker。也许是这样的?:

public List<String> results = new List<String>();

private void button1_Click(object sender, EventArgs e)
{
    When(SomeLongRunningMethod("get") == true)
    {
        // LongRunningMethod has completed.
        // display results on Form.
        foreach(string result in results)
        {
            this.Controls.Add(new Label() { Text = result; Location = new Point(5, (5 * DateTime.Now.Millisecond)); });
        }
    }
}

public void SomeLongRunningMethod(string value)
{
    if(value == "get")
    {
        // Do work.
        results.Add("blah");
    }
}

上面基本上说,“做这个,当你完成后,将结果添加到表单中。”

【问题讨论】:

  • 查看异步/等待。完全满足您的需求。

标签: c# .net winforms


【解决方案1】:

我建议您使用async/awaitTask.Run。请注意,返回结果更清晰:

private void button1_Click(object sender, EventArgs e)
{
  var results = await Task.Run(() => SomeLongRunningMethod("get"));
  foreach(string result in results)
  {
    this.Controls.Add(new Label() { Text = result; Location = new Point(5, (5 * DateTime.Now.Millisecond)); });
  }
}

public List<string> SomeLongRunningMethod(string value)
{
  var results = new List<string>();
  if(value == "get")
  {
    // Do work.
    results.Add("blah");
  }
  return results;
}

我的博客上有一系列博客文章,描述了Task.Run acts as a replacement for BackgroundWorker

【讨论】:

    【解决方案2】:

    您正在寻找的是 async / await

    private async void button1_Click(object sender, EventArgs e)
    {
        string result = await SomeLongRunningMethod("www.stackoverflow.com");
    
        // LongRunningMethod has completed.
        ....
    }
    
    public Task<string> SomeLongRunningMethod(string uri)
    {
        // Example
        return WebClient.DownloadStringAsync(new Uri(uri));
    }
    

    计算密集型操作的示例如下:

    public Task<string> SomeLongRunningMethod()
    {
      return Task.Factory.StartNew(() => 
      {
         // Perform work which requires some time to complete ...
         return "your result";
      });   
    }
    

    网络上有很多关于这个主题的信息。以下是有关该主题的广泛介绍的链接:

    http://msdn.microsoft.com/en-us/library/hh191443.aspx

    【讨论】:

    • 我建议将您的异步方法名称更改为以 Async 结尾,并使用Task.Run 代替Task.Factory.StartNew
    • .NET 4.0 没有Task.Run 方法
    【解决方案3】:

    是的,您可以使用 async/await 来执行此操作。 但是,我建议您在深入研究之前也阅读一些有关此主题的内容。

    public List<String> results = new List<String>();
    
    private async void button1_Click(object sender, EventArgs e)
    {
        var results = await SomeLongRunningMethodAsync("get");
        //Flow continues here once the long running operation has completed
        foreach(string result in results)
        {
          this.Controls.Add(new Label() { Text = result; Location = new Point(5, (5 * DateTime.Now.Millisecond)); });
        }
    }
    
    public async Task<List<string>> SomeLongRunningMethodAsync(string value)
    {
        //This is the long running operation
        //Mind you, this executes on a separate thread. 
        return await Task.Run(() =>
        {
          List<string> results = new List<string>();
          if(value == "get") 
          {
            //do work
          }
          return results;
        });
    }
    

    更多关于here

    根据@Daniel Kelley 下面的建议,确实建议在异步方法中添加Async 后缀。此外,Task.Run 通常应该比Task.TaskFactory.StartNew 更受青睐,因为内部任务会自动展开(尽管这不适用于这里,所以我也没有调整它)。

    【讨论】:

    • Task.Factory.StartNew 也比Task.Run 长,并且有一个可能令人困惑的默认任务调度程序。 Task.Run 在所有方面都很出色,应该在这里使用。更多信息on my blog.
    • @StephenCleary:完成。
    • .NET 4.0 没有 Task.Run 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多