2011-07-07 44 views
1

我遇到了一个问题,即集合中的第一个项目正在响应更新,但没有其他项目(满分为40)。我看了一遍网络寻找答案,但不幸的是,在几天之后,我仍然没有得到任何帮助。螺纹应用程序问题

揭开序幕一个线程用于检测循环调用代码:

_detectionThread = new Thread(() => _x.StartDetection()); 
_detectionThread.Start(); 

Ive得到了我的助手类的一个下面的代码简单地投票和当检测到的东西,通过事件的方式视图模型被称为:

public event EventHandler SomethingIsDetected; 
private void OnSomethingDetected() 
     { 
      if (SomethingIsDetected!= null) 
      { 
       SomethingIsDetected(this, new EventArgs()); 
      } 
     } 

代码检测回路:

var startCheckTime = DateTime.Now; 
      var nextCheck = startCheckTime.AddSeconds(PollingInterval.TotalSeconds); 

      while (_performDetection) 
      { 
       startCheckTime = DateTime.Now; 
       if (startCheckTime >= nextCheck) 
       { 
        nextCheck = startCheckTime.AddSeconds(PollingInterval.TotalSeconds); 

        { 
         var detectionTask = Task.Factory.StartNew(() => IsXConnected()); 
         IsXPresent = detectionTask.Result; 

         Thread.Sleep(TimeSpan.FromSeconds(1)); 

         if (IsXPresent) 
         { 
          Application.Current.Dispatcher.Invoke(new Action(OnSomethingDetected)); 
         } 
        } 
       } 
       Thread.Sleep(10); 
      } 

更新项目的代码。视图绑定到这里的属性(特别是CurrentItem)。项目是一个ObservableCollection

foreach (var item in Items) //loop through 40 items 
{ 
//do some operation then set the current item 
Application.Current.Dispatcher.Invoke(new Action(() => CurrentItem = item)); 
} 

虽然林步进通过(与调试器的帮助下)我注意到,该项目被udpated只是第一次。剩下的只是循环。我用一个DependencyProperty设置属性CurrentItem。

我曾尝试使用CheckAccess来使用Delegate和udpate属性,并没有帮助。

任何帮助,欢迎和感谢!

+2

1)何苦因为您在下一行阻塞,所以创建一个调用IsXConnected的任务,直到操作完成。 2)什么是IsXConnected在做什么?既然这就是我在第一个结果后返回错误,这似乎很重要。3)我意识到foreach循环中有一些代码设置CurrentItem = item,但是一开始它并没有任何意义,因为除非有阻塞调用,否则它会很快通过所有的Items和CurrentItem将最终成为Items.Last,这将是UI将会看到的唯一的东西。 –

+0

感谢您的保罗,我得到了一个UI更新位的Debug.WriteLine,这表明只有第一个项目正在调用更新位。 (即使通过调用方法来处理点1,而没有任务)。 – TheRenoRanger

+0

我相信从MainWindow.XAML.cs的构造函数执行线程是罪魁祸首。签出[这](http://stackoverflow.com/questions/6639237/wpf-custom-control-dependencyproperty-issue)发布更多信息。 – TheRenoRanger

回答

3

你的问题与多线程无关,它必须关闭如何在最后一段代码中捕获变量。你的lamba的所有共享相同的变量,即有一个item变量。由于您的lamda在循环结尾item后运行,将始终设置为Items集合中的最后一个项目。 (虽然他们可能得到的任何项目上运行,这取决于具体什么时候再运行)

编译器将其转换:

foreach (var item in Items) //loop through 40 items 
{ 
    //do some operation then set the current item 
    Application.Current.Dispatcher.Invoke(new Action(() => CurrentItem = item)); 
} 

的东西在道德上equivalend这样:

class closuseCapture { 
    private ItemType itemCapture; 

    public void Loop() { 
     foreach (var item in Items) //loop through 40 items 
     { 
      itemCapture = item; 
      //do some operation then set the current item 
      Application.Current.Dispatcher.Invoke(new Action(ActionMethod)); 
     } 
    } 

    public void ActionMethod() { 
     CurrentItem = itemCapture; 
    } 

修复的方法是在循环中声明一个变量,以便循环的每次交互都可以获得它自己的项目副本:

foreach (var item in Items) //loop through 40 items 
{ 
    var localItem = item; 
    //do some operation then set the current item 
    Application.Current.Dispatcher.Invoke(new Action(() => CurrentItem = localItem)); 
}   

见任何或所有这些的更多信息或 “访问修改关闭” 做一个谷歌搜索

http://devnet.jetbrains.net/thread/273042

Access to Modified Closure

Access to Modified Closure (2)

http://weblogs.asp.net/fbouma/archive/2009/06/25/linq-beware-of-the-access-to-modified-closure-demon.aspx

+0

感谢@ shf301。试图宣布一个局部变量,不幸的是,这也没有任何帮助。我会看看我还能做些什么...(另请阅读你放置链接的东西)。干杯。 – TheRenoRanger