线程化应用程序问题
本文关键字:问题 应用程序 线程 | 更新日期: 2023-09-27 18:01:36
我遇到了一个问题,集合中的第一个项目响应更新,但没有其他项目(40个)。我在网上寻找答案,但不幸的是,几天后我仍然一无所获。
为检测循环启动线程的调用代码:
_detectionThread = new Thread(() => _x.StartDetection());
_detectionThread.Start();
我在我的一个助手类中得到了以下代码,它只是轮询,当检测到某些东西时,通过事件的方式调用视图模型:
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)。Items是一个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));
}
当我逐步执行时(在调试转换器的帮助下),我注意到项目只是第一次更新。剩下的只是循环。我用DependencyProperty设置了CurrentItem属性。
我试过使用CheckAccess来使用Delegate和update属性,这也没有帮助。
欢迎任何帮助,谢谢!
您的问题与多线程无关,它与闭包如何在最后的代码片段中捕获变量有关。所有的都有相同的变量,也就是说只有一个item
变量。由于您的lambda在循环结束后运行,因此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));
}
在道德上等同于:
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对修改闭包的访问
对修改闭包的访问(2)
http://weblogs.asp.net/fbouma/archive/2009/06/25/linq-beware-of-the-access-to-modified-closure-demon.aspx