所以我们在VB.net中使用MVP设计模式。我们有一个简单的登录视图和界面:
Public Interface ILogonView
ReadOnly Property Username() As String
End Interface
Public Class LogonView
Implements ILogonView
Public ReadOnly Propery Username As String Implements ILogonView.Username
Get
tbUsername.Text
End Get
End Property
End Class
问题是我们需要修改Get以使其具有线程安全性。这样做意味着我们需要有选择地将代码包装在Control.Invoke()
调用中,以确保我们只能从主线程访问UI对象。
例如,如果不是使用Property执行此操作,而是使用标准getter执行此操作,我们将使用递归。类似的东西:
Function GetUsername() as String
If Me.InvokeRequired Then
Return Me.Invoke(Sub() GetUsername())
End If
Return tbUsername.Text
End Function
我的问题是 - 我们可以从属性的Getter中递归调用一个属性吗?我的Vb.net有点生疏,我无法发现完成此任务的语法魔法。
答案 0 :(得分:3)
是,不需要调用时返回。如果在第一次通过时需要,则后续通话不会。
Public ReadOnly Property GetUsername As String
Get
If tbUsername.InvokeRequired Then
Return tbUsername.Invoke(Function() GetUsername())
Else
Return tbUsername.Text
End If
End Get
End Property
请参阅Automating the InvokeRequired code pattern
您可以编写扩展方法来自动化
<Extension()>
Public Function InvokeIfRequired(Of TR)(ByVal control As Control, func As Func(Of TR)) As TR
If control.InvokeRequired Then
Return CType(control.Invoke(func), TR)
Else
Return func()
End If
End Function
<Extension()> _
Public Sub InvokeIfRequired(ByVal control As Control, action As MethodInvoker)
If control.InvokeRequired Then
control.Invoke(action)
Else
action()
End If
End Sub
然后
Public Property GetUsername As String
Get
Return tbUsername.InvokeIfRequired(Function() tbUsername.Text)
End Get
Set(value As String)
tbUsername.InvokeIfRequired(Sub() tbUsername.Text = value)
End Set
End Property
您可以在Project Property Pages&gt;&gt;中忽略与项目中的递归属性调用相关的编译器警告。编译&gt;&gt;警告配置&gt;&gt; Recursive operator or property access
= None
,但它适用于整个项目可能弊大于利。
答案 1 :(得分:0)
非递归方法
Public ReadOnly Property GetUsername As String
Get
Dim rv As String
If tbUsername.InvokeRequired Then
tbUsername.Invoke(Sub()
rv = tbUsername.Text
End Sub)
Else
rv = tbUsername.Text
End If
Return rv
End Get
End Property