线程应用程序的问题线程、应用程序、问题

2023-09-07 16:34:23 作者:心悸

Ive得到了一个问题,即集合中的第一个项目是响应的更新,但没有其他人(满分40)。 Ive有周边净是寻找答案,但遗憾的是我还在原地踏步后一两天。

Ive got an issue where the first item in the collection is responding to an update but no others (out of 40). Ive had a look around the net for answers but unfortunately Im still getting nowhere after a couple of days.

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

The calling code which kicks off a thread for the detection loop:

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

香港专业教育学院在我的辅助类之一得到了下面的code,它简单地投票和当检测到的东西,由事件的视图模型被称为方式:

Ive got the following code in one of my helper classes which simply polls and when something is detected, by way of an event the View-Model is called:

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

code检测循环:

Code for detection loop:

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);
            }

code更新项目。查看势必这里的属性(尤其是CurrentItem)。项目是一个ObservableCollection

Code for updating items. View is bound to properties here (especially CurrentItem). Items is an 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只是第一次。剩下的只是遍历。香港专业教育学院设置属性CurrentItem用的DependencyProperty。

While Im stepping through (with the help of a debugging converter) I notice that the item is udpated just the first time. The rest just loops through. Ive setup property CurrentItem with a DependencyProperty.

香港专业教育学院尝试使用的checkAccess使用代表和UDPATE财产,没有帮助任。

Ive tried using CheckAccess to use Delegate and udpate property and that didnt help either.

任何帮助是值得欢迎和感谢!

Any help is welcome and thanks!

推荐答案

您的问题无关,与多线程,它与如何在你最后code段封闭捕获变量。你兰巴的所有共享相同的变量,那就是有一个项目变量。因为循环结束后,您LAMDA的运行项目总是被设置为在项目集合中的最后一项。 (虽然他们可能得到的任何项目上运行,这取决于什么时候再运行)

Your problem has nothing to do with multi-threading, it has to with how closures capture variables in your last code snippet. You lamba's all share the same variable, that is there is a single item variable. Since your lamda's run after the end of the loop item will always be set to the the last item in the Items collection. (Although they could get run with any item, depending on exactly when then run)

编译器将其转换:

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这样:

to something morally equivalend to this:

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;
    }

解决方法是宣布你的循环内的变量,这样循环的每次交互都有自己的项目复制:

The fix is to declare a variable inside your loop so each interaction of the loop gets its own copy of the item:

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 ));
}        

请参阅上述任何或全部以获取更多信息或做一个谷歌搜索进入修改封

See any or all of these for more information or do a Google search for "Access to modified closure"

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