I need to randomly run a method that will read a string from a text file and display it with a TextBox until the lines in the file run out. It turned out that's what.

Random rand = new Random(); Timer mytimer = new Timer(); public void Timer() { mytimer.Tick += new EventHandler(Reader); mytimer.Interval = rand.Next(1000, 3000); mytimer.Enabled = true; mytimer.Start(); } public int TotalLines() { using (StreamReader r = new StreamReader(@"test.txt")) { int i = 0; while (r.ReadLine() != null) { i++; } return i; } } public void Reader(Object myObject, EventArgs myEventArgs) { StreamReader file = new StreamReader(@"test.txt"); progressBar1.Maximum = TotalLines(); for (int i = 0; i <= TotalLines(); i++) { textBox1.Text = file.ReadLine(); progressBar1.Value = i; } file.Close(); mytimer.Interval = rand.Next(1000, 3000); } private void button1_Click(object sender, EventArgs e) { Timer(); } 

But with this problem code, firstly, the string in the textbox is not drawn, and in the second, the timer chases this method in a circle. Where am I wrong?

I figured out the timer as follows

  public void Reader(Object myObject, EventArgs myEventArgs) { StreamReader file = new StreamReader(@"test.txt"); int f = TotalLines(); progressBar1.Maximum = f; for (int i = 0; i <= f; i++) { textBox1.Text = file.ReadLine(); progressBar1.Value = i; mytimer.Interval = rand.Next(1000, 3000); mytimer.Stop(); } file.Close(); } 

    1 answer 1

    I would completely abandon the old-fashioned timer and multithreading, and make it easier through async / await.

    Example:

     async Task Work(string filename, IProgress<double> progress, IProgress<string> produce) { var rnd = new Random(); progress.Report(0); var data = File.ReadLines(filename); var count = data.Count(); // внимание - может быть медленно! int i = 0; foreach (var line in data) { i++; await Task.Delay(TimeSpan.FromMilliseconds(rnd.Next(1000, 3000))); produce.Report(line); progress.Report((double)i / count); } progress.Report(1); } 

    You can run, for example, like this:

     async void OnGO(object sender, RoutedEventArgs e) { Progress<double> progress = new Progress<double>(p => ProgressReport.Value = p); Progress<string> produce = new Progress<string>(s => Target.Text += (s + Environment.NewLine)); GoButton.IsEnabled = false; await Work(FilenameBox.Text, progress, produce); GoButton.IsEnabled = true; } 
     <Window x:Class="Test.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <TextBox Name="Target"/> <ProgressBar Grid.Row="1" Name="ProgressReport" Height="15" Margin="10" Minimum="0" Maximum="1"/> <DockPanel Grid.Row="2" LastChildFill="True"> <Button Content="Go" Name="GoButton" Click="OnGO" Width="75" DockPanel.Dock="Right" Margin="10"/> <TextBox Name="FilenameBox" Margin="10"/> </DockPanel> </Grid> </Window>