Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用EventHandler调用GUI_C#_User Interface_Invoke - Fatal编程技术网

C# 使用EventHandler调用GUI

C# 使用EventHandler调用GUI,c#,user-interface,invoke,C#,User Interface,Invoke,我有一个类似“ClientSocket.cs”的类 还有另一个类“myForm.cs” 这里是问题。 我试着用BeginInvoke或直接调用writeLog。有时,我在向GuitTextBox写入时会出现InvalidOperation异常。 我不明白为什么我会收到那个信息。事件由ClientSocket对象触发,但事件处理程序与主UI线程(myForm)相关 我可以避免对类的每个EventHandler使用BeginInvoke/Invoke吗 编辑:我知道有什么区别,现在我正在尝试了解举

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

还有另一个类“myForm.cs”

这里是问题。 我试着用BeginInvoke或直接调用writeLog。有时,我在向GuitTextBox写入时会出现InvalidOperation异常。 我不明白为什么我会收到那个信息。事件由ClientSocket对象触发,但事件处理程序与主UI线程(myForm)相关

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


编辑:我知道有什么区别,现在我正在尝试了解举办该活动的最佳实践

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

或者当我使用该对象并向该处理程序添加侦听器时,是否应该将其放入

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

Cheers

事件处理程序在
myForm
中声明,但执行处理程序的线程由
ClientSocket
类的逻辑定义。如果这将是后台线程,那么事件处理程序将从后台线程引发,因此,您需要
BeginInvoke
来避免对控件的跨线程访问

换句话说:属于任何类型的任何方法都与线程无关,线程将永远执行此方法。这些东西(类型和线程)是平行的宇宙

顺便说一下,您可以替换此:

public delegate void ConnectHandler(object sender, EventArgs e);
public event ConnectHandler ConnectEvent = delegate { };
为此:

public event EventHandler ConnectEvent;

无需再创建另一个委托类型。

客户端套接字中的
this.BeginInvoke
不存在。为了能够执行
BeginInvoke
操作,必须对具有该方法的对象(您的表单)调用它

如果希望调用发生在ClientSocket类内部,则需要传入一个具有
BeginInvoke
函数的
控件

然而,如果我写这篇文章,我不会这样做。它向
ClientSocket
添加了一个不必要的要求,即必须传入
控件(调用该控件,您应该在编程中尽量避免)。就我个人而言,我会让事件在任何它想要引发的线程中传递,让消费者担心做任何特殊的调用(如果他们需要的话)

下面是我将如何编写
myForm\u 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正在做什么(),但是如果它没有与UI交互,你根本不需要进行任何调用。如果它与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);
}
private void myForm\u OnConnectEvent(对象发送方,事件参数e)
{
书面记录(“关联”);
}
私有void writeLog(字符串日志消息)
{
if(logTextBox.invokererequired)
{
logTextBox.BeginInvoke(新操作(writeLog)、logMessage);
返回;
}
var logLine=String.Format(“{0:g}:{1}{2}”,DateTime.Now,logMessage,envirorment.NewLine);
logTextBox.AppendText(logLine);
}

有关完整的解释,请参阅本MSDN帖子,MSDN对此非常清楚。现在我只想知道使用BeginInvoke的最佳实践。我应该在ClientSocket的EventHandler中还是在myForm中调用“BeginInvoke”?引用的示例调用表单的一个方法,该方法检查textBox1.InvokeRequest是否为true,然后继续设置文本。我不完全理解您的问题,因为示例中没有使用
BeginInvoke
。我理解示例,我想了解使用BeginInvoke/Invoke的最佳实践是什么。我试图解释我使用“委托处理程序”的最佳(编辑)方法,因为在WEB上的许多示例中,人们都使用这种“代码样式”。有什么区别?而且,我应该在ClientSocket的EventHandler中还是在myForm中调用“BeginInvoke”呢?回答得好。但我只能选择一个答案。太清楚了!是的,当然我写了一个糟糕的例子(用this.BeginInvoke代替myControl.BeginInvoke[ClientSocket.cs])。我来自Java和Python语言,所以我习惯使用第一个小写字母:)谢谢
public event EventHandler ConnectEvent;
// 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");
}
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);
}