Domanda

I have a WPF application developed with Prism. I am facing a typical scenario for a code change I implemented for performance improvement.

I have a UI Grid which shows a list of entities. I select some 10 entities in the Grid and try to open it, which inturn should open a new window and load the corresponding 10 entities by resolving corresponding containers and their dependencies.

The sample code is below,,, I have commented the operations that are occuring..

private void OpenSelectedEntities(List<Entity> entities)
    {
        foreach (Entity entity in entities)
        {
            if (Application.Current != null)
            {
        //I implemented opening entity in async so that 10 entities will be opened without stalling the UI.
                Dispatcher.BeginInvoke(DispatcherPriority.Background,
                                        new Action(() =>
                                        {
                                            OpenEntity(entity, false);
                                        }));
            }
        }
    }


    public void OpenEntity(Entity entity, boolean val)
   {
    //Creating Container to load the controls.

    //Adding Container to Region

    //Loading the other UI related and triggering operation threads

}

The problem I am facing is, When I select some entities and verify it in my local development environment, I am able to see all the 10 entities opened and working well. However, When I deploy the code in Server and test it there,, Only two entities were opened, the first entity and last entity in the selected entities.. I am completely clueless what is causing this problem. I have cross checked twice, I am getting this problem while calling OpenEntity as Asynchronous.

Has anyone encountered situation like this using WPF and Prism.

È stato utile?

Soluzione

It is an "Access to Modified Closure" problem. Look into that for more details.
Here's a blog post that discusses it. http://www.jarloo.com/access-to-modified-closure/

As for the fix, create a temp variable.

private void OpenSelectedEntities(List<Entity> entities)
{
    foreach (Entity entity in entities)
    {
        if (Application.Current != null)
        {
            Entity tempEntity = entity;
            Dispatcher.BeginInvoke(DispatcherPriority.Background,
                                    new Action(() =>
                                    {
                                        OpenEntity(tempEntity , false);
                                    }));
        }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top