4

Using a toolbar, written in ArcObjects, it is possible to push processing to a separate thread so that the GUI does not lock.

Is it possible to have the thread update a progress bar in the same position (lower right - arcmap) that a geoprocessing tool does?

I must be missing some obvious documentation to gain access to that progress bar update location.

2

Yes it is, but UI updates must be done on the UI thread. This hold true for Winforms, WPF as well as the ArcMap/ArcCatalog windows.

This concept is mentioned in the link you provided: sections Updating the UI from a background thread and Calling ArcObjects from a thread other than the main thread should help. Basically, you create a Winforms Control on the UI thread, but do not display it anywhere and use it merely as a means to propagate calls to the UI thread. So any ivocations of IStatusBar.ShowProgressBar, IStatusBar.StepProgressBar etc. must be effectively done from the UI thread.

Of course, no matter what you do, you must always adhere to the fact that ArcObjects cannot be used across threads, as described in the article.

Another alternative might be to wrap your functionality in a geoprocessing tool and have it execute asynchronously by the ArcGIS framework for you.

0

If you are launching a process that needs to use the map you might need to use a DispatcherTimer or WinformsTimer, depending on your operation you might be able to get by with a regular thread. Whatever you choose just make it call something like StepProgressBar below.

<!-- this is my XAML hosted in a winformhost --> 
   <ProgressBar    Width="125"
                                    Name="ProgressBar1" 
                                    Grid.Row="0"
                                    Height="15"
                                    HorizontalAlignment="Right"
                                    DockPanel.Dock="Right"
                                    Minimum="0"
                                    Maximum="32767"
                                    />



private delegate void UpdateProgressBarDelegate(System.Windows.DependencyProperty dp, object value);
        public void StepProgressBar(double step)
        {
            if (!double.IsInfinity(step))
            {
                ProgressBar1.Value += step;
                double value = ProgressBar1.Value;

                UpdateProgressBarDelegate updatePbDelegate = new UpdateProgressBarDelegate(ProgressBar1.SetValue);

                Dispatcher.Invoke(  updatePbDelegate,
                                    System.Windows.Threading.DispatcherPriority.Normal,
                                    new object[] 
                                    { 
                                        System.Windows.Controls.ProgressBar.ValueProperty, value 
                                    }
                                    );
            }
        }
0

I was able to implement what you are suggesting using a method WriteProgress:

            using System.Threading.Tasks;

            ESRI.ArcGIS.Framework.IApplication g_pApp = ArcMap.Application; //declare an instance of status bar and progress bar
            ESRI.ArcGIS.esriSystem.IStatusBar g_psbar = g_pApp.StatusBar;
            ESRI.ArcGIS.esriSystem.IStepProgressor g_pPro = g_psbar.ProgressBar;
            g_pPro.MaxRange = totalFeatureCount;

            CancellationTokenSource tokenSource = new CancellationTokenSource();
            CancellationToken ct = tokenSource.Token;

            //create a new background thread
            Task task = Task.Factory.StartNew(delegate
            {
                ct.ThrowIfCancellationRequested();
                //do some tasks here in your background thread before you update progress bar


                BeginInvoke((Action)(() => //update the progress bar in lower right
                                {
                                    WriteProgress(stepFeatureCount, g_pPro);
                                }));
                            }
            }



            void WriteProgress(int stepFeatureCount, IStepProgressor g_pPro)
            {
                g_pPro.StepValue = stepFeatureCount;
                g_pPro.Step();

            }

Hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.