【问题标题】:C# in Async Task change Label TextC# 中的异步任务更改标签文本
【发布时间】:2015-05-16 22:25:28
【问题描述】:

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

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
    }

如果您可以将 async 与 UI 一起使用会非常方便

【问题讨论】:

  • 您可以尝试在异步任务中询问“label1.InvokeRequired”并按字面意思调用吗?
  • 好的 InvokeRequired 返回 true。
  • 您正在尝试从不是 UI 线程的线程修改 UI 控件。试试label1.Text = "test";await MyAsyncMethod();label1.Text="";

标签: c# user-interface asynchronous label task


【解决方案1】:

通过您需要调用的第二个线程访问 GUI 控件。 下面的例子展示了如何正确设置标签的文本

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

希望能解决你的问题

【讨论】:

  • 没问题,这个问题让我好几个月都没有使用任务和线程
  • 这里也一样。我慢慢开始得到一些东西。
  • 对给我投反对票的人,我想让你解释一下原因。
【解决方案2】:

如果您可以将 async 与 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";
}

这是最自然的方法。

但是,如果您需要在后台线程上运行代码(例如,它实际上是受 CPU 限制的,或者您只是不想让 I/O 操作像应有的那样异步be),那么你可以使用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");
}

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

【讨论】:

  • 似乎第一个例子出错了:System.InvalidOperationException: 'Cross-thread operation not valid: Control 'labelProject' accessed from a thread other than the thread it was created on.'
  • @MatthieuCharbonnier:如果在正确建立的 UI 上下文中调用按钮单击处理程序,则不会发生这种情况。我建议你用一个最小的、可重复的例子来问你自己的问题。
  • 按钮在正确建立的 UI 上下文中被调用,并且正在发生。当使用 ConfigureAwaitawait 调用时会发生这种情况。这里描述了相同的情况stackoverflow.com/questions/37898516/…
  • @Jonathan:Control.Invoke 是一种 WinForms 特有的方式,用于后台工作将工作发送到 UI 线程。这有几个问题;这里有一些我的想法:1)后台工作通常不应该关心它开始的线程。 2)它使测试变得更加困难。 3)后台工作向UI线程发送工作是向后的;当 UI 线程是“控制器”时,代码总是更干净。 4) 此方法与特定的 UI 框架相关联。
  • @variable: label1 是一个类实例变量。您的异步方法必须是同一类上的非静态方法才能访问它。
【解决方案3】:

Task.Run 用于将 Action(非异步)封装到 Task 中。应该等待您要执行的任何任务。因此,你的Task.Run 严格来说什么都不做。

将您的 button1_Click 事件处理程序标记为异步。然后删除 Task.Run 并等待 MyAsyncMethod()

【讨论】:

  • 这只是它所做工作的简化版本。在我的代码中,我运行了一个函数,该函数执行大量 IO 和需要很长时间但没有异步功能的东西 -> 它没有运行异步
  • 所以你的同步函数不应该是异步的。然后,您将等待 Task.Run(MyMethod)。这样你就可以异步运行它。
  • 另外,由于可视线程将是等待调用的线程,因此您无需将内容编组回 UI 线程。我将很快添加一些代码示例来向您展示我的意思。
【解决方案4】:

试试这个。您无需触发新线程即可调用异步方法。编译器会帮你做的。

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

【讨论】:

    【解决方案5】:

    我认为问题和一些答案都不清楚。根据任务线程中的哪个位置,您需要更新您必须使用调用的标签。否则,您可以利用 await 并利用标准语义。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-20
      • 2017-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多