Search code examples
c#.netmultithreadingeventsevent-handling

C#: String as parameter to event?


I have a GUI-thread for my form and another thread that computes things.

The form has a richtTextBox. I want the worker-thread to pass strings to the form, so that every string is displayed in the textbox.

Everytime a new string is generated in the worker thread I call an event, and this should now display the string. But I don't know how to pass the string! This is what I tried so far:

///// Form1
private void btn_myClass_Click(object sender, EventArgs e)
{
    myClass myObj = new myClass();
    myObj.NewListEntry += myObj_NewListEntry;
    Thread thrmyClass = new Thread(new ThreadStart(myObj.ThreadMethod));
    thrmyClass.Start();
}

private void myObj_NewListEntry(Object objSender, EventArgs e)
{
    this.BeginInvoke((MethodInvoker)delegate
    {
        // Here I want to add my string from the worker-thread to the textbox!
        richTextBox1.Text += "TEXT"; // I want: richTextBox1.Text += myStringFromWorkerThread;
    });
}

///// myClass (working thread...)
class myClass
{
    public event EventHandler NewListEntry;

    public void ThreadMethod()
    {
        DoSomething();
    }

    protected virtual void OnNewListEntry(EventArgs e)
    {
        EventHandler newListEntry = NewListEntry;
        if (newListEntry != null)
        {
            newListEntry(this, e);
        }
    }

    private void DoSomething()
    {
        ///// Do some things and generate strings, such as "test"...
        string test = "test";


        // Here I want to pass the "test"-string! But how to do that??
        OnNewListEntry(EventArgs.Empty); // I want: OnNewListEntry(test);
    }
}

Solution

  • Like this

    public class NewListEntryEventArgs : EventArgs
    {
        private readonly string test;
    
        public NewListEntryEventArgs(string test)
        {
            this.test = test;
        }
    
        public string Test
        {
            get { return this.test; }
        }
    }
    

    then you declare your class like this

    class MyClass
    {
        public delegate void NewListEntryEventHandler(
            object sender,
            NewListEntryEventArgs args);
    
        public event NewListEntryEventHandler NewListEntry;
    
        protected virtual void OnNewListEntry(string test)
        {
            if (NewListEntry != null)
            {
                NewListEntry(this, new NewListEntryEventArgs(test));
            }
        }
    }
    

    and in the subscribing Form

    private void btn_myClass_Click(object sender, EventArgs e)
    {
        MyClass myClass = new MyClass();
        myClass.NewListEntry += NewListEntryEventHandler;
        ...
    }
    
    private void NewListEntryEventHandler(
        object sender,
        NewListEntryEventArgs e)
    {
        if (richTextBox1.InvokeRequired)
        {
            this.Invoke((MethodInvoker)delegate
                {             
                    this.NewListEntryEventHandler(sender, e);
                });
            return;
        }
    
        richTextBox1.Text += e.Test;
    }
    

    I've taken the liberty of making the NewListEntryEventArgs class immutable, since that makes sense. I've also partially corrected your naming conventions, simplified and corrected where expedient.