You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#转VB.Net后Delegate事件调用报错,如何正确使用RaiseEvent?

问题描述

我是Delegate新手,将一段C#的连接状态变更事件相关代码转换为VB.Net后,在调用ConnectionStatusChanged事件的BeginInvoke和EndInvoke方法时,出现BC32022错误,提示事件无法直接调用,需使用RaiseEvent语句。但我不清楚原代码的具体逻辑,也不知道RaiseEvent的处理程序应该如何编写,希望得到帮助。

原C#代码

public delegate void delConnectionStatusChanged(EventDrivenTCPClient sender, ConnectionStatus status);
public event delConnectionStatusChanged ConnectionStatusChanged;
private ConnectionStatus _ConStat;

public ConnectionStatus ConnectionState
{
    get
    {
        return _ConStat;
    }
    private set
    {
        bool raiseEvent = value != _ConStat;
        _ConStat = value;
        if (ConnectionStatusChanged != null && raiseEvent)
            ConnectionStatusChanged.BeginInvoke(this, _ConStat, new AsyncCallback(cbChangeConnectionStateComplete), this);
    }
}


private void cbChangeConnectionStateComplete(IAsyncResult result)
{
    var r = result.AsyncState as EventDrivenTCPClient;
    if (r == null)
        throw new InvalidOperationException("Invalid IAsyncResult - Could not interpret as a EDTC object");
    r.ConnectionStatusChanged.EndInvoke(result);
}

转换后的VB.Net代码

Public Delegate Sub delConnectionStatusChanged(ByVal sender As EventDrivenTCPClient, ByVal status As ConnectionStatus)
Public Event ConnectionStatusChanged As delConnectionStatusChanged
Private _ConStat As ConnectionStatus

Public Property ConnectionState As ConnectionStatus
    Get
        Return _ConStat
    End Get
    Private Set(ByVal value As ConnectionStatus)
        Dim [raiseEvent] As Boolean = value <> _ConStat
        _ConStat = value
        If ConnectionStatusChanged IsNot Nothing AndAlso [raiseEvent] Then ConnectionStatusChanged.BeginInvoke(Me, _ConStat, New AsyncCallback(AddressOf cbChangeConnectionStateComplete), Me)
    End Set
End Property


Private Sub cbChangeConnectionStateComplete(ByVal result As IAsyncResult)
    Dim r = TryCast(result.AsyncState, EventDrivenTCPClient)
    If r Is Nothing Then Throw New InvalidOperationException("Invalid IAsyncResult - Could not interpret as a EDTC object")
    r.ConnectionStatusChanged.EndInvoke(result)
End Sub

报错信息

Error BC32022 'Public Event ConnectionStatusChanged As EventDrivenTCPClient.delConnectionStatusChanged' is an event, and cannot be called directly. Use a 'RaiseEvent' statement to raise an event.
(中文翻译:错误 BC32022:“Public Event ConnectionStatusChanged As EventDrivenTCPClient.delConnectionStatusChanged”是一个事件,无法直接调用。请使用“RaiseEvent”语句引发事件。)

解决方案

原代码逻辑解析

原C#代码核心逻辑:当ConnectionState属性值发生变化时,异步触发ConnectionStatusChanged事件,通过BeginInvoke异步调用事件处理程序,再通过回调方法cbChangeConnectionStateComplete调用EndInvoke完成异步操作的清理。

VB.Net修正代码

VB.Net对事件封装更严格,类内部无法直接对事件调用BeginInvoke/EndInvoke,必须先获取事件对应的委托实例再操作。修正后的代码如下:

Public Delegate Sub delConnectionStatusChanged(ByVal sender As EventDrivenTCPClient, ByVal status As ConnectionStatus)
Public Event ConnectionStatusChanged As delConnectionStatusChanged
Private _ConStat As ConnectionStatus

Public Property ConnectionState As ConnectionStatus
    Get
        Return _ConStat
    End Get
    Private Set(ByVal value As ConnectionStatus)
        Dim raiseEvent As Boolean = value <> _ConStat
        _ConStat = value
        ' 先获取事件对应的委托实例,避免直接操作事件
        Dim handler As delConnectionStatusChanged = ConnectionStatusChanged
        If handler IsNot Nothing AndAlso raiseEvent Then
            ' 将委托实例传入AsyncState,供回调方法使用
            handler.BeginInvoke(Me, _ConStat, AddressOf cbChangeConnectionStateComplete, handler)
        End If
    End Set
End Property

Private Sub cbChangeConnectionStateComplete(ByVal result As IAsyncResult)
    ' 从AsyncState中取出委托实例
    Dim handler As delConnectionStatusChanged = TryCast(result.AsyncState, delConnectionStatusChanged)
    If handler Is Nothing Then
        Throw New InvalidOperationException("Invalid IAsyncResult - 无法转换为delConnectionStatusChanged委托")
    End If
    ' 调用委托的EndInvoke完成异步操作
    handler.EndInvoke(result)
End Sub

关键修正说明

  1. 获取委托实例:将ConnectionStatusChanged事件赋值给局部变量handler,这是VB.Net允许调用委托方法的前提,避免直接操作事件。
  2. 传递委托到回调:把handler作为BeginInvoke的AsyncState参数传入,回调方法中直接通过该参数获取委托实例,调用EndInvoke完成异步清理,规避VB.Net不能通过实例访问事件方法的限制。

内容的提问来源于stack exchange,提问作者Tim Makins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 14:25:19