views:

58

answers:

4

How do i add an entry in a listbox in a window that is in another thread. My Problem is, that i have to threads. One working thread, that does all the actual work and one thread for a window where i want to display status information. I tried to pass the form window as paramater in the constructor, but when i call it i get an exception.

Here is some of my code to illustrate the problem:

public partial class Mainform : Form
{
    private string db = String.Empty;
    private string password = String.Empty;
    private string sqlinifile = String.Empty;
    DatabaseListener dbListener;
    StatusWindow statusWindow;

    public Mainform()
    {
        //
        // The InitializeComponent() call is required for Windows Forms designer support.
        //
        InitializeComponent();

        //
        // TODO: Add constructor code after the InitializeComponent() call.
        //
        db = "EWAG";
        password = "secret";
        sqlinifile = "C:\\Programme\\Unify\\Team Developer 5.2\\sql.ini";
        textBoxDB.Text = db;
        textBoxPwd.Text = password;
        textBoxSqlIni.Text = sqlinifile;

        statusWindow = new StatusWindow();
        dbListener = new DatabaseListener(statusWindow);
    }

    public void threadStarter()
    {
        this.dbListener.startSynchronizing(5);

    }
    void Button1Click(object sender, EventArgs e)
    {
        this.db = textBoxDB.Text;
        this.password = textBoxPwd.Text;
        this.sqlinifile = textBoxSqlIni.Text;

        if (dbListener.connectToDatabase(db,"sysadm", password, sqlinifile)) 
        {
            this.Hide();
            statusWindow.Show();
            Thread synchronizer = new Thread(new ThreadStart(threadStarter));
            synchronizer.Start();

        }
    }       

}
+4  A: 

Use the .Invoke(), Luke.

Seriously, to talk to some controls on the form from another thread, you have to Invoke() some method so the property setters that talks to window handles are serialized to main UI thread and it's message pump.

Alternatively, use timer that is on the main UI thread to gather information and put them in the listbox.

Or use hybrid approach, one thread to gather the data, put it into queue that is not tied into UI, and timer to dequeue it and display data on the form. I used it on occasion because receiving data rate was too big and it would block the UI.

Daniel Mošmondor
+1  A: 

Use Control.Invoke to call any code that should touch the UI.

Giorgi
A: 

check out this link:

http://blogs.msdn.com/b/csharpfaq/archive/2004/03/17/91685.aspx

KhanZeeshan
A: 

In addition to using Invoke(), check to see if you need to Invoke with the current thread with the InvokeRequired property of the object you want to modify. You can create a delegate and make a method threadsafe by using the pattern in the cod below.

    private delegate void LogLineDelegate(string ShortText, string LongText);
    private void LogLine(string ShortText, string LongText)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new LogLineDelegate(LogLine), new object[] { ShortText, LongText });
            return;
        }
        sbLog.Append(string.Format("{0:MM-dd-yy} {0:HH:mm:ss.fff} - {1}: {2}.\r\n", DateTime.Now, ShortText, LongText));
        textBoxLog.Text = sbLog.ToString();
    }
Gil