Question

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.

Was it helpful?

Solution

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);
                                    }));
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top