我正在尝试将VS2010 C#4.0框架的代码块转换为VS2008 VB.NET 3.5 Framework。我非常不确定如何继续,因为我不熟悉VB.NET和VS2008,我发现两种环境之间的差异令人沮丧。我已经从最初的C#中剔除了大部分不相关的代码,希望能够提供一个可以指出解决方案的问题的清晰示例。
我确实尝试了一些代码转换器,但是lambdas将它们绊倒了。
我将第一个lambda转换为一个简单的For Each
构造,看起来很好。
然而,第二个lambda(传递给ThreadPool.QueueUserWorkItem
调用)引起了我的不确定性。由于lambda正在使用在lambda体外声明的taskcount
var,我对使这个代码对我的目标环境(VS2008 / VB.Net / 3.5)友好并保持代码的最佳方法犹豫不决与原始实现尽可能相似。除非没有其他办法,否则我不希望明确将taskcount
推送到WaitCallback
。
public void sendAndBlock(List<ISendable> msgs)
{
int taskCount = msgs.Count;
AutoResetEvent fini = new AutoResetEvent(false);
msgs.ForEach(m =>
{
ThreadPool.QueueUserWorkItem(nil =>
{
this.send(m);
//threadsafe decrement and if we have no tasks left then unblock.
if (0 == Interlocked.Decrement(ref taskCount))
{
fini.Set();//signal our main thread to proceed
}
}, m);
});
//block our main thread
fini.WaitOne();
}
答案 0 :(得分:4)
不幸的是,与Visual Studio 2008一起使用的VB版本将要求你将其分解为三个方法(原始的,每个lambda表达式加一个),因为旧版本的VB.Net还不支持多个-line lambda表达式。我们必须调整一些东西,这样我们就可以将lambda表达式放到一行中,以便正确地关闭捕获的变量。如果您使用相同版本的Visual Studio,VB.Net将能够以与C#相同的方式执行此操作(至少在本例中),因为Visual Studio 2010中包含的VB.Net版本支持多个-line lambda表达式。
我认为这样做会,但检查一下:我在回复窗口输入了所有这些并且它很复杂我可能有一两个错误。
Public Sub sendAndBlock(ByVal msgs As List(Of ISendable))
Dim taskCount As Integer = msgs.Count
Dim fini As New AutoResetEvent(False)
'vb.net for vs2008 is limited to single-line lambdas.
' But we still need to create a closure to capture the fini and taskCount variables
' Means we can't translate old code line-for-line
' Solution is to abstract the old lambda expressions out to their own methds that we can call in a single line
msgs.ForEach(Function(m) QueueMessage(m, fini, taskCount))
fini.WaitOne()
End Sub
Private Sub QueueMessage(ByVal msg As ISendable, ByVal signaler As AutoRestEvent, ByRef taskCount As Integer)
ThreadPool.QueueUserWorkItem(Function(n) SendQueuedMessage(msg, taskCount, signaler), msg);
End Sub
Private Sub SendQueuedMessage(ByVal msg As ISendable, ByRef TaskCount As Integer, ByVal signaler As AutoResetEvent)
Me.send(msg)
'Not sure about this line, because `Set` is a reserved word in VB
If Interlocked.Decrement(taskCount) = 0 Then signaler.Set()
End Sub
我或许可以将其归结为两种方法而不是三种方法,因为其中一种额外的方法缩减为一行,但为了简单和可读性,我将把它留在这里。
最后,如果能够从Visual Studio 2010中定位.Net 3.5就足够了,您可以使用更接近原始内容的东西,因为您可以使用Visual Studio 2010中较新的VB语言语法功能.Net 3.5。
答案 1 :(得分:-1)
Public Sub sendAndBlock(msgs As List(Of ISendable))
Dim taskCount As Integer = msgs.Count
Dim fini As New AutoResetEvent(False)
msgs.ForEach(Function(m)
ThreadPool.QueueUserWorkItem(Function(nil)
Me.send(m)
'threadsafe decrement and if we have no tasks left then unblock.
If 0 = Interlocked.Decrement(taskCount) Then
'signal our main thread to proceed
fini.[Set]()
End If
End Function, m)
End Function)
'block our main thread
fini.WaitOne()
End Sub