0

I'm working on a WindowsForm and trying to import data from a file, meanwhile I'd like to display the new data on sreen as soon as I read it in.

My basic code looks like this:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        Read_in();
    }

    List<Data> _list = new List<Data>();

    public void Read_in()
    {
        using (StreamReader sr = new StreamReader("in.txt"))
        {
            while (!sr.EndOfStream)
            {
                Data d = new Data
                {
                    a = sr.ReadLine()
                };
                _list.Add(d);
                Controls.Add(d.pb);
            }
        }
    }
}

class Data
{
    public string a;
    public PictureBox pb = new PictureBox()
    {
        BackColor = Color.Red
    };
}

The problem is that my data is only displayed when Read_in() is finished. How can I help this?

Here's a post similar to this one, but I couldn't understand it: Why won't control update/refresh mid-process

Community
  • 1
  • 1
BenG
  • 53
  • 1
  • 1
  • 9

2 Answers2

1

Thats because the data is being read in the UI thread. You will have to spawn a new thread and load data in that, thus freeing the UI thread for updates.

As Alexei suggested here is the bit of explanation:

enter image description here

Note that the UI thread is blocked as long as UI update is being performed in usual process, whereas in multithreaded process, background worker does all the updation all you need to take care of is the Syncing.

Please modify the code as follows and let me know:

public void Read_in()
{
    BackgroundWorker backgroundWorker1 = new BackgroundWorker();
    backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
    backgroundWorker1.RunWorkerAsync();

}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    using (StreamReader sr = new StreamReader("in.txt"))
    {
        while (!sr.EndOfStream)
        {
            Data d = new Data
            {
                a = sr.ReadLine()
            };
            if(this.InvokeRequired)
            {
                 this.Invoke((MethodInvoker)delegate
                 {
                     _list.Add(d);
                     Controls.Add(d.pb);
                 });

            }
            else
            {
                 _list.Add(d);
                 Controls.Add(d.pb);

            }
        }
    }
}
Abhinav
  • 2,085
  • 1
  • 18
  • 31
  • 1
    +0: Note that your post is exactly what OP commented as "I couldn't understand"... I'm not sure how your sentence explain freezing UI concept better than linked post. – Alexei Levenkov Dec 19 '13 at 18:25
  • Thank you, It works. You helped me to understand a new thing! :) – BenG Dec 19 '13 at 19:41
  • @Abhinav Is it neccesary to write _list.Add(d); in the if(this.InvokeRequred) statement? – BenG Dec 20 '13 at 21:17
  • Not at all, but you might wanna use some sort of syncing to make sure no other thread touches `_list` while the BackgroundWorker does. For current example, you can take `_list` outta `InvokeRequired` block. – Abhinav Dec 20 '13 at 21:52
1

A thread is like a line in the supermarket. Now think that you have only one checkout. The guy with your files is on the checkout. And the guy with the painting for the controls is in the back of the line. The painting guy cant pay on the checkout, so he can't paint the controls. So he is blocked because of the file guy on the checkout.

Your gui thread is the line to the checkout. A way that the painting guy can go through the checkout is to open another checkout. So he can pay and go through the checkout. After that he can paint the controls. So to open another cash is to open a new thread. On the new thread you can do the file reading. With that the painting guy is not blocked on the checkout through the file guy.

Or you set two woman on the checkout with: http://msdn.microsoft.com/de-de/library/system.io.streamreader.readlineasync(v=vs.110).aspx so that the checkout is not block trough the file guy.

tire0011
  • 1,048
  • 1
  • 11
  • 22