异步任务中的C#更改标签文本

sav*_*eff 3 c# user-interface label asynchronous task

以下代码不会更改文本并停止执行任务

private void button1_Click(object sender, EventArgs e)
    {
        label1.Text = "Test";
        Task.Run(() => MyAsyncMethod());
    }

    public async Task MyAsyncMethod()
    {
        label1.Text = "";
        //everything from here on will not be executed
    }
Run Code Online (Sandbox Code Playgroud)

如果你可以与UI一起使用异步,那将会非常方便

Ste*_*ary 10

如果你可以与UI一起使用异步,那将会非常方便

设计async经过精心设计,您可以自然地使用UI.

在我的代码中,我运行一个功能,执行大量的IO和需要很长时间的东西

如果你有异步I/O方法(你应该),那么你可以这样做:

private async void button1_Click(object sender, EventArgs e)
{
  label1.Text = "Test";
  await MyMethodAsync();
}

public async Task MyMethodAsync()
{
  label1.Text = "";
  await ...; // "lot of IO and stuff"
  label1.Text = "Done";
}
Run Code Online (Sandbox Code Playgroud)

这是最自然的方法.

但是,如果您需要在后台线程上运行代码(例如,它实际上是CPU绑定的,或者如果您只是不希望使I/O操作像应该的那样异步),那么您可以使用IProgress<T>:

private void button1_Click(object sender, EventArgs e)
{
  label1.Text = "Test";
  var progress = new Progress<string>(update => { label1.Text = update; });
  await Task.Run(() => MyMethod(progress));
}

public void MyMethod(IProgress<string> progress)
{
  if (progress != null)
    progress.Report("");
  ...; // "lot of IO and stuff"
  if (progress != null)
    progress.Report("Done");
}
Run Code Online (Sandbox Code Playgroud)

在任何情况下,现代代码都不应使用Control.Invoke或(甚至更糟)Control.InvokeRequired.


leA*_*lon 8

通过您需要调用的第二个线程访问GUI控件.以下示例显示如何正确设置标签的文本

  private void setLabel1TextSafe(string txt)
  { 
       if(label1.InvokeRequired)
           label1.Invoke(new Action(() => label1.Text = txt));
       else
           label1.Text = txt;
  }
Run Code Online (Sandbox Code Playgroud)

我希望这能解决你的问题