gpt4 book ai didi

c# - 使用事件处理程序进行 GUI 调用

转载 作者:行者123 更新时间:2023-12-02 17:02:18 25 4
gpt4 key购买 nike

我有一个类似“ClientSocket.cs”的类

  class ClientSocket {
public delegate void ConnectHandler(object sender, EventArgs e);
public event ConnectHandler ConnectEvent = delegate { };

protected void OnConnectEvent(EventArgs e) {
ConnectHandler ev = ConnectEvent;
ev(this, e);
}

}

还有另一个类“myForm.cs”

public partial class myForm : Form {
private ClientSocket client;

private void button1_Click(object sender, EventArgs e) {
client = new ClientSocket();
client.ConnectEvent += myForm_OnConnectEvent;

client.connect();
}


// Handler for ConnectEvent
private void myForm_OnConnectEvent(object sender, EventArgs e) {
//this.BeginInvoke((MethodInvoker)delegate { writeLog("Connected"); });

writeLog("Connected");
}

// Function that write a log string to a TextBox
public writeLog(string log) {
guiTextBox.AppendText(log);
}
}

问题来了。我尝试使用 BeginInvoke 调用 writeLog 或直接调用它。有时,我在写入 guiTextBox 时会收到 InvalidOperationException。我不明白为什么我会收到这条消息。该事件由 ClientSocket 对象触发,但事件处理程序与主 UI 线程 (myForm) 相关。

我可以避免对类的每个 EventHandler 使用 BeginInvoke/Invoke 吗?

<小时/>

编辑:我明白有什么区别,现在我尝试了解调用事件的最佳实践。

在 BASE 类中引发事件时,我是否应该放置 BeginInvoke/Invoke 方法(在这种情况下为 ClientSocket)

    protected void OnConnectEvent(EventArgs e) {
ConnectHandler ev = ConnectEvent;

this.BeginInvoke((MethodInvoker)delegate { ev(this, e);});
}

或者我应该把它当我使用该对象并向该处理程序添加监听器时

    // Handler for ConnectEvent used in GUI (myForm)
private void myForm_OnConnectEvent(object sender, EventArgs e) {
this.BeginInvoke((MethodInvoker)delegate { writeLog("Connected"); });
}

干杯

最佳答案

ClientSocket 内的 this.BeginInvoke 不存在。为了能够执行 BeginInvoke ,必须在具有该方法的对象上调用它(在您的情况下为您的表单)。

如果您希望在 ClientSocket 类内部进行调用,则需要传入具有 BeginInvoke 函数的 Control

但是,如果我写这篇文章,我就不会采用这种方法。它向 ClientSocket 添加了一个不必要的要求,即您必须传入一个Control(这称为 Tightly Coupling并且您应该在编程中尽量避免它)。就我个人而言,我会让事件在它想要引发的任何线程中传递,并让消费者担心进行任何特殊调用(如果他们甚至需要的话)。

这是我编写myForm_OnConnectEvent的方式,该模式检查我们是否需要调用,如果需要,它会使用相同的参数再次调用该函数,但这次是在 UI 线程上。

// Handler for ConnectEvent used in GUI (myForm)
private void myForm_OnConnectEvent(object sender, EventArgs e)
{
if(this.InvokeRequired)
{
this.BeginInvoke(new ConnectHandler(myForm_OnConnectEvent), new object[] {sender, e});
return;
}

writeLog("Connected");
}
<小时/>

顺便说一句,我不知道 writeLog 正在做什么( it should have a capital W by the way ),但如果它不与 UI 交互,则根本不需要执行任何调用。如果它与 TextBox 或 UI 上的其他内容交互,就是我进行调用的地方。

private void myForm_OnConnectEvent(object sender, EventArgs e) 
{
writeLog("Connected");
}

private void writeLog(string logMessage)
{
if(logTextBox.InvokeRequired)
{
logTextBox.BeginInvoke(new Action<string>(writeLog), logMessage);
return;
}

var logLine = String.Format("{0:g}: {1}{2}", DateTime.Now, logMessage, Enviorment.NewLine);
logTextBox.AppendText(logLine);
}

关于c# - 使用事件处理程序进行 GUI 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19916251/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com