2011-01-26 91 views
2
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函数,我希望将加载推迟到可用时。在VB.NET中推迟执行?

的问题是上述代码导致编译器错误,因为a ByRef param cannot be used in lambda expressions

任何想法如何以正确的方式做到这一点?

+0

那么等待连接打开时发生了什么? – ChaosPandion 2011-01-26 03:27:22

+0

我不认为“回避”一词意味着你的想法。 – Gabe 2011-01-26 03:33:17

+0

@ChaosPandio:到那时执行不同的查询,连接状态是`ConnectionState.Connecting`等等,我在等待连接变成`Open`,或者至少`Closed`,所以我可以明确地打开它,场景是连接被占用,LoadData被另一个线程调用。 @加贝:我的意思是递归 @ – Shimmy 2011-01-26 03:39:10

回答

3

因为它可能被指向不再存在,一旦拉姆达execuetes在堆栈上的位置,则无法在拉姆达使用ByRef参数。您只需使用更“永久”的存储位置即可。您可以传入一个对象,其中您可以设置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#中,这是一个三步过程。首先,您必须声明一个变量来保存lambda表达式,并将其值设置为null。然后你创建lambda,它现在可以引用它来取消订阅。最后,您可以使用lambda订阅该事件。

0

你必须在你的调用线程不知道如果变量已被LoadData()呼叫

填入你需要做的THI情况下,问题是这样的:

  • 执行座当负载完成
  • 在您的装载机,直到加载完成
  • 引发事件设定一个公开可见的字段,以指示载荷状态

一个(可能)折衷办法是返回一个自定义对象,而不是一个IEnumerable

自定义对象的可以立即尝试加载数据,并保持重新尝试,直到成功。如果在加载发生之前读取自定义对象的结果集,则阻塞该线程直至加载完成,否则返回结果集

在这种情况下,如果Load事件发生和正在使用的数据 - 您的程序可以继续运行直到它需要数据。无论这个我是否有用,完全取决于你使用的是什么。阻断执行

更多信息: 这取决于一点你如何成为意识到连接备份,但这样的:

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参数相比,而不是一个函数?你只是“返回”一个对象,所以我不太明白这个好处。不是说它会在功能上产生巨大的差异,但它会更具可读性......