locked
Set ProgressBar's Visibility property in create_task crashes the app

    Question

  • I put an ProgressBar control inside the bottom AppBar to give users a visual indication of the operation progress, just like Metro IE's address bar.

        <Page.BottomAppBar>
            <AppBar Padding="10,0,10,0">
                <Grid>
                    <StackPanel>
                        <ProgressBar x:Name="OperationProgress" Margin="2" Height="5" IsIndeterminate="True" Foreground="White" Visibility="Collapsed"/>
                    </StackPanel>

    In my code, I put the CPU heavy code inside a Lambda expression of create_task:

        Rect rectContent = GetElementRect(safe_cast<FrameworkElement^>(sender));
        create_task(menu->ShowForSelectionAsync(rectContent, Windows::UI::Popups::Placement::Above)).then([this](IUICommand^ command)
        {
            if (command != nullptr)
            {
                // User has selected a menu item
                int const id = safe_cast<IBox<int>^>(command->Id)->Value;
                if ( (id==1 || id==3) && ((int)gViewDimension != id-1) ) {
                    OperationProgress->Visibility = Windows::UI::Xaml::Visibility::Visible;
                    create_task([this,id]
                    {
                        // CPU heavy code start
                        gViewDimension = (GRAPHICS_DIMENSION)(id-1);
                        mgral::setDimension((int)gViewDimension);
                        gGraphicsMan.set_graphics_dimension(gViewDimension);
                        gGraphicsMan.OnDimensionChanged();
                        // CPU heavy code end
    
                        m_renderNeeded = true;
                        // Issue: uncomment the line below crashes the app
                        OperationProgress->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
                    });
                }
            }
        });

    The reason to use create_task is that the App UI thread won't be blocked by heavy computation code. Otherwise, the ProgressBar control won't be shown at all. The issue is my app crash when the code below is executed.

    OperationProgress->Visibility = Windows::UI::Xaml::Visibility::Collapsed;

    Sunday, October 12, 2014 12:21 PM

Answers

  • Hi Leonard,

    Here you have a create_task, we can understand all your code inside are not a UI thread, and now you would like to change the Visibility of a UIElement from no-UI thread, an exception is expected.

    Try with RunAsync method to see if you can successfully set the visibility for the progress bar.

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Monday, October 13, 2014 7:10 AM
    Moderator
  • After some trials and errors, I finally work it out by combining create_task and RunAsync.


    • Marked as answer by Leonard Monday, October 13, 2014 12:01 PM
    • Edited by Leonard Tuesday, October 14, 2014 10:47 PM
    Monday, October 13, 2014 12:00 PM

All replies

  • Hi Leonard,

    Here you have a create_task, we can understand all your code inside are not a UI thread, and now you would like to change the Visibility of a UIElement from no-UI thread, an exception is expected.

    Try with RunAsync method to see if you can successfully set the visibility for the progress bar.

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Monday, October 13, 2014 7:10 AM
    Moderator
  • Thank you. I've tried the RunAsync method but it does not work. Here is the code

    	Rect rectContent = GetElementRect(safe_cast<FrameworkElement^>(sender));
    	create_task(menu->ShowForSelectionAsync(rectContent, Windows::UI::Popups::Placement::Above)).then([this](IUICommand^ command)
    	{
    		if (command != nullptr)
    		{
    			// User has selected a menu item
    			int const id = safe_cast<IBox<int>^>(command->Id)->Value;
    			if ( (id==1 || id==3) && ((int)gViewDimension != id-1) ) {
    				OperationProgress->Visibility = Windows::UI::Xaml::Visibility::Visible;
    				Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, 
    										ref new Windows::UI::Core::DispatchedHandler([this,id]()
    				{
    					gViewDimension = (GRAPHICS_DIMENSION)(id-1);
    					mgral::setDimension((int)gViewDimension);
    					gGraphicsMan.set_graphics_dimension(gViewDimension);
    					gpMapGraph->OnDimensionChanged();
    					gGraphicsMan.OnDimensionChanged();
    					m_renderNeeded = true;
    					// Issue: uncomment the line below crashes the app if the code segment is put inside create_task
    					OperationProgress->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
    				}));
    			}
    		}
    	});
    

    The progressbar is not shown though the app continue to run.

    I thought the failure results from the fact that RunAsync puts the work to main UI thread. The CPU sensitive code prevents the UI from updating itself. After the computation, the progressbar is set to collapsed. The overall effect is that progressbar is not visible during the whole process.

    Monday, October 13, 2014 11:39 AM
  • After some trials and errors, I finally work it out by combining create_task and RunAsync.


    • Marked as answer by Leonard Monday, October 13, 2014 12:01 PM
    • Edited by Leonard Tuesday, October 14, 2014 10:47 PM
    Monday, October 13, 2014 12:00 PM