+-
c#-传递委托(带有参数)作为参数
背景

我已使用DeveloperFusion.com上的转换器将下面的C#代码(在TreeViewAdv文件AbortableThreadPool.cs中找到)转换为VB.net代码.这是一个学习项目,我将自动转换引起的错误缩减为一个错误,我完全迷失了.

C#

private void HandleItem(object ignored)
{
    WorkItem item = null;
    try
    {
        lock (_callbacks)
        {
            if (_callbacks.Count > 0)
            {
                item = _callbacks.First.Value;
                _callbacks.RemoveFirst();
            }
            if (item == null)
                return;
            _threads.Add(item, Thread.CurrentThread);

        }
        ExecutionContext.Run(item.Context, delegate { item.Callback(item.State); }, null);
    }
    finally
    {
        lock (_callbacks)
        {
            if (item != null)
                _threads.Remove(item);
        }
    }
}

VB.Net

Private Sub HandleItem(ByVal ignored As Object)
    Dim item As WorkItem = Nothing
    Try
        SyncLock _callbacks
            If _callbacks.Count > 0 Then
                item = _callbacks.First.Value
                _callbacks.RemoveFirst()
            End If
            If item Is Nothing Then
                Return
            End If

            _threads.Add(item, Thread.CurrentThread)
        End SyncLock
        ExecutionContext.Run(item.Context, Sub() item.Callback(item.State), Nothing)
    Finally
        SyncLock _callbacks
            If item IsNot Nothing Then
                _threads.Remove(item)
            End If
        End SyncLock
    End Try
End Sub

问题

该行:

ExecutionContext.Run(item.Context, Sub() item.Callback(item.State), Nothing)

在VB代码中会出现此错误:必须将属性访问分配给该属性或使用其值.

假设转换器只是语法错误,我用AddressOf替换了Sub()并得到了错误:’AddressOf’操作数必须是方法的名称(不带括号).但是,我不能删除括号而不要删除我要传递给item.Callback(即item.State)的争论.这可以通过以下事实得到确认,当我删除(item.state)时,会收到另一个错误:方法’Friend ReadOnly属性回调为System.Threading.WaitCallback’没有与委托’Delegate Sub ContextCallback(状态为对象)兼容的签名)’.

问题

1.)对作者在该行中试图做的事情的简单理解.

2.)一种可行的VB代码解决方案,以使其可以用作C#代码.

编辑:我认为可能会有帮助的更多信息.回调和状态是WorkItem类的ReadOnly属性,分别是WaitCallback和Object类型.老实说,这使我感到困惑,因为这表明C#代码正在将值传递给只读属性.

要求的信息

这是Class WorkItem

Imports System.Collections.Generic
Imports System.Text
Imports System.Threading

Namespace Aga.Controls.Threading
    Public NotInheritable Class WorkItem
        Private _callback As WaitCallback
        Private _state As Object
        Private _ctx As ExecutionContext

        Friend Sub New(ByVal wc As WaitCallback, ByVal state As Object, ByVal ctx As ExecutionContext)
            _callback = wc
            _state = state
            _ctx = ctx
        End Sub

        Friend ReadOnly Property Callback() As WaitCallback
            Get
                Return _callback
            End Get
        End Property

        Friend ReadOnly Property State() As Object
            Get
                Return _state
            End Get
        End Property

        Friend ReadOnly Property Context() As ExecutionContext
            Get
                Return _ctx
            End Get
        End Property
    End Class
End Namespace
最佳答案
Run方法接受带有单个参数的 ContextCallback委托,但是您的委托不接受任何参数.

也许尝试让您的委托接受单个参数:

ExecutionContext.Run(item.Context, Sub(state) item.Callback(item.State), Nothing)

更新资料

经过仔细检查,与C#相比,VB.NET处理委托的方式似乎存在一些关键差异.基本上,从属性或字段解析委托并同时调用它会遇到麻烦.但是,您可以像下面这样在委托上调用Invoke方法:

ExecutionContext.Run(item.Context, Sub(state) item.Callback.Invoke(item.State), Nothing)

但是,如果您不喜欢直接在委托上调用方法,我相信您将必须使用多行lambda来完成此任务.像这样:

ExecutionContext.Run(item.Context, 
    Sub(state) 
        Dim cb = item.Callback
        cb(item.State)
    End Sub, Nothing)

或者像这样,在我看来这更容易理解.

Dim contextCallback As ContextCallback = 
    Sub(state) 
        Dim cb = item.Callback
        cb(item.State)
    End Sub
ExecutionContext.Run(item.Context, contextCallback, Nothing)
点击查看更多相关文章

转载注明原文:c#-传递委托(带有参数)作为参数 - 乐贴网