C# in Async Task change Label Text

前端 未结 5 717
清酒与你
清酒与你 2021-01-03 09:50

The following Code does not change the Text and stops executing the Task

private void button1_Click(object sender, EventArgs e)
    {
        label1.Text = \         


        
相关标签:
5条回答
  • 2021-01-03 10:32

    for accessing a GUI control through a second thread you need to invoke. 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

    0 讨论(0)
  • 2021-01-03 10:33

    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
         }
    }
    
    0 讨论(0)
  • 2021-01-03 10:44

    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. 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;
               });
    
        }
    
    0 讨论(0)
  • 2021-01-03 10:51

    Task.Run is used to envelope an Action (that is not async) into a Task. Any Task that you want to execute should be awaited. Thus, that Task.Run of yours is rigorously doing nothing.

    Mark that button1_Click event handler of yours as async. Then remove that Task.Run and instead do await MyAsyncMethod().

    0 讨论(0)
  • 2021-01-03 10:56

    would be really handy if you could use async together with the UI

    The design of async was carefully done so you can use it naturally with the UI.

    in my code i run a function that does a lot of IO and stuff that takes a long time

    If you have asynchronous I/O methods (which you should), then you can just do this:

    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 (e.g., 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>:

    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.

    0 讨论(0)
提交回复
热议问题