传递Delegate(带参数)作为参数

时间:2013-11-06 05:47:35

标签: c# vb.net delegates

背景

我已使用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代码中的

给出了以下错误:属性访问必须分配给属性或使用其值。

假设转换器的语法错误,我将Sub()替换为AddressOf,我得到错误:'AddressOf'操作数必须是方法的名称(没有括号)。但是,我不能删除括号而不删除我传递给item.Callback(即item.State)的争论。这是因为当我删除(item.state)时,我收到另一个错误:方法'Friend ReadOnly属性回调因为System.Threading.WaitCallback'没有与委托'Delegate Sub ContextCallback兼容的签名( state As Object)'。

问题

1。)简单了解作者在该行中尝试做什么。

2。)VB代码的可行解决方案,以便它可以作为C#代码运行。

修改:我认为可能会有所帮助的更多信息。 Callback和State是Class 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

1 个答案:

答案 0 :(得分:3)

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)