VB.NET 中的延迟执行?
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< /code> param 不能在 lambda 表达式中使用
。
知道如何以正确的方式做到这一点吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您不能在 lambda 中使用
ByRef
参数,因为它可能指向堆栈上的某个位置,而该位置在 lambda 执行后就不再存在。您所要做的就是使用更“永久”的存储位置。您可以传入一个具有IEnumerable(Of T)
属性的对象,您可以设置该属性以分配结果。一个可能更好的选择是传入一个委托 (
Action>
),该委托接受结果并执行调用者对结果所需的任何操作。下面是一个 C# 示例:您可以像这样调用
LoadData
:请注意我的实现的细微差别。例如,它不会在事件处理程序中调用自身,因为如果处理程序以
Open
以外的状态调用,这将导致它重新订阅该事件。一旦连接打开,它也会取消订阅该事件。我不确定这将如何转换为 VB,但在 C# 中,这是一个 3 步过程。首先,您必须声明一个变量来保存 lambda 并将其值设置为 null。然后您创建 lambda,它现在可以引用自身来取消订阅。最后,您可以使用 lambda 来订阅事件。You cannot use a
ByRef
parameter in a lambda because it could be pointing to a location on the stack which no longer exists once the lambda execuetes. All you have to do is use a more "permanent" storage location. You can pass in an object with a property ofIEnumerable(Of T)
that you can set in order to assign the result.A probably better option is to pass in a delegate (
Action<IEnumerable<T>>
) that accepts the result and performs whatever action the caller requires with the result. Here's an example in C#:And you would invoke
LoadData
like this:Note the nuances of my implementation. For example, it does not call itself within the event handler because that will cause it to resubscribe to the event if the handler is ever called with a state other than
Open
. It also unsubscribes from the event once the connection opens. I'm not sure how this would translate to VB, but in C# this is a 3-step process. First you must declare a variable to hold the lambda and set its value to null. Then you create the lambda, which can now reference itself to unsubscribe. And finally you can use the lambda to subscribe to the event.您遇到的问题是,您的调用线程不知道该变量是否已由
LoadData()
调用填充。在这种情况下,您需要执行以下操作:
一种(可能的)妥协是返回自定义对象而不是 IEnumerable
自定义对象可以立即尝试加载数据并不断重试,直到成功。如果在加载发生之前读取自定义对象的结果集,则阻塞线程直到加载完成,否则返回结果集
在这种情况下,如果加载发生和正在使用的数据之间存在延迟,您就会受益- 您的程序可以继续运行,直到需要数据为止。这是否有用完全取决于您使用它的目的。
有关阻止执行的更多信息:
这在一定程度上取决于您如何意识到连接已备份,但类似于:
您是否有任何理由将其作为带有 ByRef 参数的子程序而不是函数来执行此操作?你只“返回”一个对象,所以我不太明白这样做的好处。并不是说它会在功能上产生巨大的差异,但它会更具可读性......
You've got a problem in that your calling thread has no idea if the variable has been populated by the
LoadData()
callIn thi case you need to do something like:
One (possible) compromise would be to return a custom object instead of an IEnumerable
The custom object could immediately attempt to load the data and keep re-trying until success. If the result set of the custom object is read before a load has occured, block the thread until the load completes, otherwise return the result set
In this scenario, you get a benefit if there's a delay between the Load occuring and the data being used - your program can continue on until it needs the data. Whether this i useful or not depends entirely on what you're using it for.
More information on blocking execution:
It depends a little on how you become aware that the connection is back up but something like:
Is there any reason you're doing this as a sub with ByRef parameters as opposed to a function? You're only "returning" one object so I don't quite see the benefit. Not that it would make a huge difference functionally but it would be more readable...