我有一个用于表单的 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);
}
}
像这样
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来创建一个新类。
创建您自己的
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=vs.95).aspx
我一直在寻找类似的解决方案。这是比其他答案更现代的语法:
带有字符串的事件参数
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;
});
}