简体   繁体   English

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

[英]C# in Async Task change Label Text

The following Code does not change the Text and stops executing the 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
    }

would be really handy if you could use async together with the UI 如果你可以与UI一起使用异步,那将会非常方便

would be really handy if you could use async together with the UI 如果你可以与UI一起使用异步,那将会非常方便

The design of async was carefully done so you can use it naturally with the UI. async的设计经过精心设计,因此您可以在UI中自然使用它。

in my code i run a function that does a lot of IO and stuff that takes a long time 在我的代码中,我运行一个功能,执行大量的IO和需要很长时间的东西

If you have asynchronous I/O methods (which you should), then you can just do this: 如果你有异步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";
}

That's the most natural approach. 这是最自然的方法。

However, if you need to run code on a background thread (eg, it's actually CPU-bound, or if you just don't want to make your I/O operations asynchronous like they should be), then you can use IProgress<T> : 但是,如果你需要在后台线程上运行代码(例如,它实际上是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");
}

Under no circumstances should modern code use Control.Invoke or (even worse) Control.InvokeRequired . 在任何情况下,现代代码都不应使用Control.Invoke或(甚至更糟) Control.InvokeRequired

for accessing a GUI control through a second thread you need to invoke. 通过您需要调用的第二个线程访问GUI控件。 following example shows how to set a label's text properly 以下示例显示如何正确设置标签的文本

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

I hope this solves your problem 我希望这能解决你的问题

Task.Run is used to envelope an Action (that is not async) into a Task. Task.Run用于将Action(不是异步)封装到Task中。 Any Task that you want to execute should be awaited. 应该等待您要执行的任何任务。 Thus, that Task.Run of yours is rigorously doing nothing. 因此,你的Task.Run严厉无所事事。

Mark that button1_Click event handler of yours as async. button1_Click事件处理程序标记为异步。 Then remove that Task.Run and instead do await MyAsyncMethod() . 然后删除该Task.Run ,而不是等待MyAsyncMethod()

Try this. 尝试这个。 You don't need to fire a new thread to invoke the async method. 您不需要触发新线程来调用异步方法。 compiler will do it for you. 编译器会为你做。

private void button1_Click(object sender, EventArgs e)
    {
        label1.Text = "Test";
        MyAsyncMethod();
    }
public async Task MyAsyncMethod()
{
    return await Task.Run(() =>{
    label1.Text = "";
    //everything from here on will not be executed
     }
}

I think both the questions and some of the answers are not clear. 我认为问题和一些答案都不清楚。 Depending on where in the task thread you need to update the label you have to use invoke. 根据您需要更新标签的任务线程中的位置,您必须使用invoke。 Otherwise you can leverage await and leverage the standard semantics. 否则,您可以利用等待并利用标准语义。

    private async void button1_Click(object sender, EventArgs e)
    {
        label1.Text = "Starting to run a long task... carry on...";
        await snooze(3);
        label1.Text = "Done with long task";
    }

    public Task<int> snooze(int seconds)
    {
        label1.Text = "zzzz...";
        return Task.Run(
        () => {
            label1.Invoke(new Action(() => label1.Text = "For some reason I need to alert you here.. bad dream perhaps...direct access to label1 will fail"));
            Thread.Sleep(seconds * 1000);
            return  seconds;
           });

    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM