jpiccolo
jpiccolo

Reputation: 778

Textbox won't update until method done

I am trying to use a textbox to show Tasks completing. Basically like how console application would show what is happening.

However the text in the textbox is only updating after Window_Loaded_1 has completed, then all the text gets displayed instead of in realtime.

xaml code:

<Window x:Class="timelineTesting.Windows.CreateNewProject"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="CreateNewProject" Height="300" Width="579" Loaded="Window_Loaded_1">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <TextBox Text="{Binding Path=LogData, UpdateSourceTrigger=PropertyChanged}" />
</Grid>

C# code:

public partial class CreateNewProject : Window, INotifyPropertyChanged
{
    private string _data;
    public String LogData
    {
        get
        {
            return _data;
        } 
        set
        {
            _data = value;
            OnPropertyChanged("LogData");
        }
    }

    public CreateNewProject()
    {
        InitializeComponent();
        this.DataContext = this;   
    }

    private void Window_Loaded_1(object sender, RoutedEventArgs e)
    {
        Task t = new Task(() => Directory.CreateDirectory(this.ProjectName));

        LogData+="Starting new project creation...." + Environment.NewLine;
        LogData += "Creating project directory '" + ProjectName + "'....";
        try
        {
            t.Start();
            t.Wait();
        }
        catch (Exception ex)
        {
            LogData += "Error:" + Environment.NewLine;
            LogData += ex.InnerException.ToString();
        }

        LogData+= "Done!" + Environment.NewLine;

        t = new Task(() => File.Copy(this.VideoFilePath, newVideoPath));
        LogData+= "Copying video file to project directory....";
        try
        {
            t.Start();
            t.Wait();
        }
        catch (Exception ex)
        {
            LogData+= "Error:" + Environment.NewLine;
            LogData+= ex.InnerException.ToString();
        }

        LogData+= "Done!" + Environment.NewLine;
        // many more tasks
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

Upvotes: 6

Views: 2723

Answers (3)

Stephen Cleary
Stephen Cleary

Reputation: 457197

Use await:

private async void Window_Loaded_1(object sender, RoutedEventArgs e)
{
  Task t = Task.Run(() => Directory.CreateDirectory(this.ProjectName));
  LogData += "Starting new project creation...." + Environment.NewLine;
  LogData += "Creating project directory '" + ProjectName + "'....";
  try
  {
    await t;
  }
  catch (Exception ex)
  {
    LogData += "Error:" + Environment.NewLine;
    LogData += ex.ToString();
  }

  LogData += "Done!" + Environment.NewLine;

  t = Task.Run(() => File.Copy(this.VideoFilePath, newVideoPath));
  LogData += "Copying video file to project directory....";
  try
  {
    await t;
  }
  catch (Exception ex)
  {
    LogData += "Error:" + Environment.NewLine;
    LogData += ex.ToString();
  }

  LogData += "Done!" + Environment.NewLine;

  // many more tasks
}

Upvotes: 3

ΩmegaMan
ΩmegaMan

Reputation: 31721

Use a Background Worker instead which has a ProgressChanged event which could update your textbox with a concurrent status.

See the article: C# WPF: Threading, Control Updating, Status Bar and Cancel Operations Example All In One which provides an example.

Upvotes: 2

David Basarab
David Basarab

Reputation: 73351

t.Wait() is a blocking call. Meaning you are really not doing multi threading. You start the task and then wait for it to complete. What you should do is await for the task to complete.

Upvotes: 3

Related Questions