混合WPF,LinqToSql和多线程是个坏主意吗?

时间:2009-01-14 10:36:34

标签: wpf multithreading linq-to-sql

我的情况大致类似于this guy,但我现在不需要更改通知

我有一个显示层次结构的WPF应用程序。使用LinqToSql查询检索每个节点的子节点。当有一个帖子时,该应用程序可以正常运行。

现在我想让事情变得更快......通过异步加载孩子。触发线程,进行数据库提取,完成后为子节点创建相应的树节点。

<HierarchicalDataTemplate DataType="{x:Type viewmodels:NodeDM}" ItemsSource="{Binding Path=Children}">

昨天发生了一些颠簸后,我发现WPF数据绑定允许通过Binding上的IsAsync属性进行此操作。所以我做了以下更改

<HierarchicalDataTemplate .. ItemsSource="{Binding Path=Children, IsAsync=True}">

现在它的混乱,最初的一堆节点在异常爆发之前通过了火。在这里粘贴第一个......

System.Windows.Data Error: 16 : Cannot get 'Children' value (type 'ObservableCollection`1') from '' (type 'NodeDM'). BindingExpression:Path=Children; DataItem='NodeDM' (HashCode=29677729); target element is 'TreeViewItem' (Name=''); target property is 'ItemsSource' (type 'IEnumerable') TargetInvocationException:'System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidCastException: Specified cast is not valid.
   at System.Data.SqlClient.SqlBuffer.get_Int32()
   at System.Data.SqlClient.SqlBuffer.get_Value()
   at System.Data.SqlClient.SqlDataReader.GetValueInternal(Int32 i)
   <snipped around 20-30 lines>
   at System.Data.Linq.Table`1.GetEnumerator()
   at System.Data.Linq.Table`1.System.Collections.Generic.IEnumerable<TEntity>.GetEnumerator()
   at System.Linq.Lookup`2.CreateForJoin(IEnumerable`1 source, Func`2 keySelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.<JoinIterator>d__61`4.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at ICTemplates.Models.NodeDM.Load_Children()
   at ICTemplates.Models.NodeDM.get_Children()

其他包括

System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.

我有一个变形树,其中一些节点无法加载。我有一个单例实例的almightly LinqToSql DataContext类,它与数据库进行通信。所以我尝试了一个锁,以便多个工作线程不会同时访问它......但没有运气。

partial class Node
{
  public IEnumerable<Segment> Children
  {
    lock (MyDatabaseDataContext.m_lockObject)
    {
      return // LINQ Query to join 2 tables and return a result
    }
  }

恢复IsAsync更改会让事情再次变得美好。 为什么IsAsync属性搞乱了LinqToSql? WPF Treeview足以让普通人拔掉头发。

1 个答案:

答案 0 :(得分:0)

您的问题似乎来自于使用相同的连接对象进行读取。当您具有同步数据访问权限时,如果您记得在读取之间打开/关闭,则通常就足够了。你要改变你的GetChildren代码,以便在每次调用时创建新的连接(以及命令/数据读取器等),这样多个线程就不会踩到彼此的脚趾。此外,如果结果缓存在某些结构的内存中,请尝试使用锁同步访问该结构。您不希望一个线程尝试枚举您的元素,而另一个线程尝试添加新元素。