C#:字符串作为事件参数?

问题描述 投票:0回答:5

我有一个用于表单的 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);
    }
}
c# .net multithreading events event-handling
5个回答
26
投票

像这样

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
类设为不可变,因为这是有道理的。我还部分纠正了您的命名约定,在方便的地方进行了简化和纠正。


5
投票

您需要通过继承EventArgs来创建一个新类。


3
投票

创建您自己的

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;
    });
}

1
投票

一般来说,您需要继承

EventArgs
并添加
string
属性,然后将您的事件设为
EventHandler<YourEventArgs>
类型,但这是
BackgroundWorker
的经典案例。

示例在这里: http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

这里: C# backgroundWorker 报告字符串?


0
投票

我一直在寻找类似的解决方案。这是比其他答案更现代的语法:

带有字符串的事件参数

public class StringEventArgs: EventArgs
{
   public StringEventArgs(string myString)
   {
       MyString = myString;
   }

   public string MyString { get; } // private set: only ctor can set it
}

myClass(工作线程...)

class myClass
{
    public event EventHandler<StringEventArgs> NewListEntry; // no delegate declaration anymore

    public void ThreadMethod()
    {
        DoSomething();
    }

    private void DoSomething()
    {
        string test = "test";
        NewListEntry?.Invoke(this, new StringEventArgs(test)); // no OnNewListEntry() anymore
    }
}

表格1

private void btn_myClass_Click(object sender, EventArgs e)
{
    var myObj = new myClass();
    myObj.NewListEntry += OnNewListEntry;
    var myThread = new Thread(new ThreadStart(myObj.ThreadMethod));
    myThread.Start();
}

private void OnNewListEntry(Object sender, StringEventArgs e)
{
    this.BeginInvoke((MethodInvoker)delegate
    {
        // Here I want to add my string from the worker-thread to the textbox!
        richTextBox1.Text += e.MyString;  
    });
}
© www.soinside.com 2019 - 2024. All rights reserved.