private void UpdatePackagePerformanceVisualization()
        {
            try
            {
                lock (syncRoot)
                {
                    if (process == null)
                    {
                        return;
                    }

                    lTickerCounter++;

                    bool bProcessExited = process.HasExited; //capture the status of the process at this point so we can ensure to execute the logic below as a unit rather than the process exiting halfway through the logic below and leaving things in an inconsistent state
                    if (bProcessExited)
                    {
                        string sStatus = "Finished";
                        if (this.ExecutionCancelled)
                        {
                            sStatus = "Cancelled";
                        }

                        TimeSpan ts = new TimeSpan();
                        ts = ts.Add(DateTime.Now.Subtract(process.StartTime));
                        this.lblStatus.Text = "Status: " + sStatus + "            Time: " + ts.ToString().Substring(0, 8);
                    }
                    else
                    {
                        TimeSpan ts = new TimeSpan();
                        ts = ts.Add(DateTime.Now.Subtract(process.StartTime));
                        this.lblStatus.Text = "Status: Executing            Time: " + ts.ToString().Substring(0, 8);

                        //if the package is still running, then only update the grid every other call to this function
                        if (lTickerCounter % 2 == 1)
                        {
                            return;
                        }
                    }

                    if (bProcessExited)
                    {
                        timer1.Enabled = false;
                        timer1.Stop();
                        StopButton.Enabled = false;
                        System.Threading.Thread.Sleep(1000); //pause just in case we need another second for the log events to quit flowing
                    }

                    DtsLogEvent[] events = logFileLoader.GetEvents(bProcessExited);
                    foreach (DtsLogEvent ee in events)
                    {
                        eventParser.LoadEvent(ee);
                        if (ee.Event == BidsHelperCapturedDtsLogEvent.OnError)
                        {
                            standardOutputWindow.ReportCustomError(OutputWindowErrorSeverity.Error, ee.Message, null, null, this.projectItem.Name);
                        }
                    }

                    //TODO: future: only refresh when the Performance tab is visible? only if there are performance problems
                    this.ganttGrid.SuspendLayout();
                    this.iDtsGanttGridRowDataBindingSource.DataSource = eventParser.GetAllDtsGanttGridRowDatas();
                    this.ganttGrid.Refresh();
                    this.ganttGrid.ResumeLayout();

                    if (bProcessExited)
                    {
                        System.IO.File.Delete(this.modifiedPackagePath);

                        for (int i = 0; i < 20; i++)
                        {
                            try
                            {
                                System.IO.File.Delete(this.logFilePath);
                                break;
                            }
                            catch
                            {
                                //problem deleting... wait half a second then try again
                                System.Threading.Thread.Sleep(500);
                            }
                        }
                        if (System.IO.File.Exists(this.logFilePath))
                        {
                            MessageBox.Show("Unable to delete log file because another process was using it:\r\n" + this.logFilePath);
                        }

                        timer1.Enabled = false;
                        timer1.Stop();

                        process = null;
                        this.StartButton.Enabled = true;
                        this.StopButton.Enabled  = false;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\r\n" + ex.StackTrace);
                timer1.Stop();
            }
        }