C#: строка как параметр события?
У меня есть GUI-поток для моей формы и другой поток, который вычисляет вещи.
форма имеет richtTextBox. Я хочу, чтобы рабочий поток передавал строки в форму, чтобы каждая строка отображалась в текстовом поле.
каждый раз, когда в рабочем потоке создается новая строка, я вызываю событие, и теперь должна отображаться строка. Но я не знаю, как передать строку! Вот что я пробовал до сих пор:
///// 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);
    }
}
            4 ответов
такой
public class NewListEntryEventArgs : EventArgs
{
    private readonly string test;
    public NewListEntryEventArgs(string test)
    {
        this.test = test;
    }
    public string Test
    {
        get { return this.test; }
    }
}
тогда вы объявляете свой класс следующим образом
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));
        }
    }
}
и в подписке 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;
}
я взял на себя смелость сделать NewListEntryEventArgs класс неизменяемым, так как это имеет смысл. Я также частично исправил ваши соглашения об именах, упрощенные и исправленные там, где это целесообразно.
создайте свою собственную версию EventArgs.
делай так:
public class MyEventArgs : EventArgs
{
   public string MyEventString {get; set; }
   public MyEventArgs(string myString)
   {
       this.MyEventString = myString;
   }
}
затем в вашем коде замените EventArgs С MyEventArgs создать MyEventArgs объект с вашей строкой в нем.
тогда вы можете получить к нему доступ с помощью MyEventArgs экземпляр .MyEventString.
таким образом, вы бы сделали что-то вроде этого:
///// myClass (working thread...)
class myClass
{
    public event EventHandler NewListEntry;
    public void ThreadMethod()
    {
        DoSomething();
    }
    protected virtual void OnNewListEntry(MyEventArgs 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";
        OnNewListEntry(new MyEventArgs(test));
    }
}
и в форме:
private void myObj_NewListEntry(Object objSender, MyEventArgs e)
{
    this.BeginInvoke((MethodInvoker)delegate
    {
        // Here I want to add my string from the worker-thread to the textbox!
        richTextBox1.Text += e.MyEventString;
    });
}
В общем, вам нужно наследовать EventArgs и добавить string свойство, а затем сделайте свое событие типа EventHandler<YourEventArgs>, но это классический случай для BackgroundWorker. 
образец здесь: http://msdn.microsoft.com/en-us/library/cc221403 (v=против 95).aspx
и здесь: C# backgroundWorker сообщает строку?