3

Background

I have converted the C# code below (found in TreeViewAdv file AbortableThreadPool.cs) into VB.net code using the converter found at DeveloperFusion.com. This is a learning project and I have whittled the errors caused by the auto-conversion down to this one error, and I am completely lost.

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

The Problem

The line:

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

in the VB code gives this error: Property access must assign to the property or use its value.

Assuming that the converter just got the syntax wrong I replaced Sub() with AddressOf and I got the error: 'AddressOf' operand must be the name of a method (without parentheses). However, i cannot remove the parentheses without also removing the arguement that I am passing to item.Callback (namely, item.State). This is confirmed by the fact that when I remove (item.state), I recieve another error: Method 'Friend ReadOnly Property Callback As System.Threading.WaitCallback' does not have a signature compatible with delegate 'Delegate Sub ContextCallback(state As Object)'.

The Question(s)

1.) A simple understanding of what the author is trying to do in that line.

2.) A workable solution for the VB code so that it will function as the C# code was intended.

Edit: Some more information that I think might help. Callback and State are ReadOnly properties of Class WorkItem, of types WaitCallback and Object respectively. Honestly, this confuses me as that would suggest that the C# code is passing a value to a read-only property.

Requested Information

Here is the 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
4

1 回答 1

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)
于 2013-11-06T05:58:26.957 回答