Asynchronous OOB Splash Screen Animation

Answered Asynchronous OOB Splash Screen Animation

  • Monday, September 19, 2011 11:24 AM
     
     

    Hi all,

    I am producing a Silverlight OOB application which requires a bulk loading operation on startup. I have produced a simple UserControl to be shown as a splash screen, with a rotating image playing in a stoyboard, started within the UserControl OnLoaded event. This splash screen has a minimum display time of 5 seconds.

    I have placed the bulk loading code within the DoWork method of a new BackgroundWorker running asynchronously to the UI thread, but my splash screen animation never runs - the animation stays on the first frame and disappears when the load has completed, which rather defeats the point of the splash screen! I know the storyboard itself is fine, as the animation plays when there is relatively little work to be done, but the problem occurs when the work load is high.

    Do I need to just accept that the storyboard will not truly execute asynchronously (given the large size of the loading task), or does anyone have a suggestion that may help?

    Cheers,

    'Firebird

All Replies

  • Monday, September 19, 2011 2:42 PM
     
     

    May be you can show the SplashScreen before loading and close the splashscreen on the Loaded event.

    If you can share the code cn able to fix it

  • Tuesday, September 20, 2011 3:36 AM
     
     

    Thanks for the quick reply.

    That's exactly what I am doing; I show the splash screen directly from Application_Startup, the set a flag on completion of the loading operation to allow the splash screen to close and reveal the main interface underneath. I believe the problem arises as the amount of processing required for the loading stage is quite high, but I cannot believe that Silverlight Isn't up to the challenge using BackgroundWorker or equivalent.

    I am using a custom Splash Screen controller class with an initialise function called in application startup:

            public static void Initialize<T>(UserControl splashcontrol, int width, int height, WindowState postWindowState, bool initializeOnLoad, double minSplashTime)
            {           
                if (App.Current.RootVisual == null)
                {
                    Width = width;
                    Height = height;
                    PostWindowState = postWindowState;
                    SplashControl = splashcontrol;
                    DateTime n = DateTime.Now;
                    StartTime = n;
                    MinSplashTime = n.AddMilliseconds(minSplashTime);
    
                    IsChangeOnLoad = initializeOnLoad;
    
                    if (App.Current.IsRunningOutOfBrowser)
                    {
                        App.Current.MainWindow.Width = Width;
                        App.Current.MainWindow.Height = Height;
                    }
    
                    CoreScreenType = typeof(T);
    
                    LayoutRoot = new Grid();
                    LayoutRoot.VerticalAlignment = VerticalAlignment.Stretch;
                    LayoutRoot.HorizontalAlignment = HorizontalAlignment.Stretch;
                    LayoutRoot.Children.Add(splashcontrol);
                    App.Current.RootVisual = LayoutRoot;
    
                    CreateCoreView();
                }
            }
    
            private static void CreateCoreView()
            {
                DispatcherTimer timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromMilliseconds(500);
                timer.Tick += delegate(object sender, EventArgs e)
                {
                    ((DispatcherTimer)sender).Stop();
                    
                    CoreView = (Control)Activator.CreateInstance(CoreScreenType);
                    CoreView.Opacity = 0;
                    CoreView.IsHitTestVisible = false;
                    
                    if (IsChangeOnLoad)
                    {
                        CoreView.Loaded += new RoutedEventHandler(CoreView_Loaded);
                    }
                    LayoutRoot.Children.Add(CoreView);
    
                };
                timer.Start();           
            }
    
            private static void CoreView_Loaded(object sender, RoutedEventArgs e)
            {
                CloseSplash();
            }


    Within the constructor for my 'CoreView' I then create a background worker to run async an carry out a bulk XML load-parse task and set a flag on completion which tells my splash screen to close within 'CloseSplash()'
    Anything obviously stupid in this methodology? Could it be because I have the code in the constructor of my core view, rather than in an OnLoaded event, and construction resources are being tied up?

    Cheers for your help,

    'Firebird
  • Wednesday, September 21, 2011 3:07 AM
     
     

    Hi,

    I suggest you to refer to the link below:

    http://blogs.cynergysystems.com/2011/02/25/creating-a-silverlight-out-of-browser-splash-screen/

    And download the full source code for the example: SplashScreen.zip

    First, create a Storyboard for your Splash.

    <Grid x:Name="LayoutRoot" Background="White">
            <Grid.Triggers>
                <EventTrigger>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation 
                    Storyboard.TargetName="image"
                    Storyboard.TargetProperty="Width"
                    From="200" To="500" Duration="0:0:2"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Grid.Triggers>
            <Image Name="image" Source="/SplashScreen;component/splash.jpg"/>
        </Grid>

     Then, delete the Thread.Sleep(10000) in LongLoadingStub.xaml.cs

    Then, change the code

    timer.Interval = TimeSpan.FromMilliseconds(500);

     to

     timer.Interval = TimeSpan.FromMilliseconds(2000);

    Hope it can help you.

     


     

     

  • Wednesday, September 21, 2011 4:43 AM
     
     Answered

    Hi, and thanks for your reply.

    My code is already based on that example, and the code I posted in my previous post was part of it.

    I have now solved my problem; the thread that I set up to run my loading code was called within a DispatcherTimer, thus executing on the UI thread and stalling my splash screen animation. I got around the issue by passing a reference to the custom DataGrid that I wished to popuate with the loaded files, and using a couple of BackgroundWorkers.

    Thanks again for your input though,

    'Firebird

  • Wednesday, November 09, 2011 8:54 AM
     
     

    Do you have an example of your solution. I am running into the same problem I believe.