Private Sub LoadData(Of T)(ByVal query As ObjectQuery(Of T),
ByRef result As IEnumerable(Of T))
If Connection.State = ConnectionState.Open Then
result = query.ToArray
Else
AddHandler Connection.StateChange,
Sub(sender As Object, e As StateChangeEventArgs)
LoadData(query, result)
End Sub
End If
End Sub
在上面的代码中,我试图在连接不可用时递归LoadData函数,我想将加载推迟到可用时。
问题是上面的代码导致了编译器错误,因为a ByRef
param cannot be used in lambda expressions。
如何以正确的方式做到这一点?
答案 0 :(得分:3)
你不能在lambda中使用ByRef
参数,因为它可能指向堆栈上的一个位置,一旦lambda execue就不再存在。您所要做的就是使用更“永久”的存储位置。您可以传入一个属性为IEnumerable(Of T)
的对象,您可以设置该对象以分配结果。
一个可能更好的选择是传入一个接受结果的委托(Action<IEnumerable<T>>
)并执行调用者对结果所需的任何操作。这是C#中的一个例子:
void LoadData<T>(ObjectQuery<T> query, Action<IEnumerable<T>> action)
{
if (Connection.State == ConnectionState.Open)
action(query.ToArray());
else
{
// create a lambda to handle the next state change
StateChangeEventHandler lambda = null;
lambda = (sender, e) =>
{
// only perform our action on transition to Open state
if (Connection.State == ConnectionState.Open)
{
// unsubscribe when we're done
Connection.StateChange -= lambda;
action(query.ToArray());
}
}
// subscribe to connection state changes
Connection.StateChange += lambda;
}
}
你会像这样调用LoadData
:
LoadData(query, results => listBox.DataSource = results);
请注意我的实施细微差别。例如,它不会在事件处理程序中调用自身,因为如果使用Open
以外的状态调用处理程序,则会导致它重新订阅事件。一旦连接打开,它也会取消订阅事件。我不确定这会如何转化为VB,但在C#中这是一个3步骤的过程。首先,您必须声明一个变量来保存lambda并将其值设置为null。然后你创建lambda,它现在可以引用自己取消订阅。最后,您可以使用lambda订阅该事件。
答案 1 :(得分:0)
你遇到的问题是你的调用线程不知道变量是否已被LoadData()
调用填充
在这种情况下,您需要执行以下操作:
一个(可能的)妥协是返回自定义对象而不是IEnumerable
自定义对象可以立即尝试加载数据并继续重试直到成功。如果在发生加载之前读取自定义对象的结果集,则阻塞该线程直到加载完成,否则返回结果集
在这种情况下,如果负载发生和正在使用的数据之间存在延迟,您将获益 - 您的程序可以继续,直到需要数据。这是否有用完全取决于你使用它的目的。
有关阻止执行的更多信息: 这取决于你如何意识到连接已经恢复,但是有点像:
Public Sub LoadData(Of T)(ByVal query As ObjectQuery(Of T), ByRef result As IEnumerable(Of T))
While Not Connection.State = ConnectionState.Open
Threading.Thread.Sleep(100) 'Pick a decent value for this delay based on how likely it is the connection will be available quickly
End While
result = 'Use the connection to get your data
End Sub
你是否有任何理由将此作为带有ByRef参数的子而不是函数?你只是“返回”一个物体,所以我不太看到它的好处。并不是说它会在功能上产生巨大的差异,但它会更具可读性......