Como implementar corretamente um BackgroundWorker com atualizações ProgressBar?

-Atualizado - 14/10 também perguntou issoquestão

Para dar uma ideia clara do que está acontecendo e levando em conta os comentários e deste artigoAqui

O que eu realmente quero fazer agora é invocar um novo formulário com uma barra de progresso e executá-lo e animá-lo enquanto meu thread em segundo plano executa meu longo processo no banco de dados e invoca um evento de fechamento de formulário

O trabalhador em segundo plano está configurado aqui

 public partial class MainWindow : Window
{
    //Declare background workers
    BackgroundWorker bw = new BackgroundWorker();
    BackgroundWorker bwLoadCSV = new BackgroundWorker();
    BackgroundWorker bwProgressBar = new BackgroundWorker();

Então os delegados adicionaram aqui

  public MainWindow()
    {
        bwLoadCSV.WorkerReportsProgress = true;
        bwLoadCSV.WorkerSupportsCancellation = true;
        bwLoadCSV.DoWork += new DoWorkEventHandler(bwLoadCSV_DoWork);
        bwLoadCSV.ProgressChanged += new ProgressChangedEventHandler(bwLoadCSV_ProgressChanged);
        bwLoadCSV.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwLoadCSV_RunWorkerCompleted);

A chamada é feita aqui a partir da classe da janela principal

  private void CSV_Load_Click(object sender, RoutedEventArgs e)
    ///Function to read csv into datagrid
    ///
    {
        //Turn Cursor to wait
        System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;

        //Test connection to sql server
        if (CHHoursDataProvider.IsDatabaseOnline() == false)
        {
            System.Windows.Forms.MessageBox.Show("Can not establish contact with sql server" + "\n" + "Contact IT", "Connection Error");
            //Set UI picture
            return;
        }
        //Set a control to update the user here
        tbLoadDgStat.Visibility = Visibility.Visible;

        tbLoadDgStat.Text = "Getting data templete from Database...";
        string FilePath = txFilePath.Text;
        if (bwLoadCSV.IsBusy != true)
        {
            //load the context object with parameters for Background worker
            bwCSVLoadContext Context = new bwCSVLoadContext();
            Context.Site = cBChSite.Text;
            Context.FilePath = txFilePath.Text;
            Context.FileName = fileTest;
            Context.Wageyear = cbWageYear.Text;
            Context.Startdate = ((DateTime)dpStartDate.SelectedDate);
            Context.Enddate = ((DateTime)dpEndDate.SelectedDate);

            bwLoadCSV.RunWorkerAsync(Context);                

        }

O trabalhador de segundo plano trabalha

private void bwLoadCSV_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        bwCSVLoadContext Context = e.Argument as bwCSVLoadContext;


        worker.ReportProgress((10));
        if ((worker.CancellationPending == true))
        {
            e.Cancel = true;

        }
        else
        {
            // Perform a time consuming operation and report progress load csv into datagrid.

Para relatar o trabalho em segundo plano, faço isso. É aqui que eu estou tentando carregar uma nova chamada de formulário ProgressDialog que tem uma barra de progresso, que eu estou tentando definir como Indeterminable, para que ele simplesmente "varre" meu formulário ProgressDialoge para mostrar ao usuário algo que ainda está acontecendo. Eu usei a parte de repórter do trabalho em segundo plano porque acredito que tenha acesso ao thread da janela principal e espero que o método invoke seja chamado a partir do thread da janela principal, mas não tenho certeza

Aqui é o repórter

 private void bwLoadCSV_ProgressChanged(object sender, ProgressChangedEventArgs e)

    {


        this.Dispatcher.Invoke((MethodInvoker)delegate { tbLoadDgStat.Visibility = Visibility.Visible; });
        //tbLoadDgStat.Visibility = Visibility.Visible;


        //this.progressBar1.Value = e.ProgressPercentage;//This works but pauses on long steps
        if (e.ProgressPercentage == 10)
        {
            //Try to open a new form with a class ProgressDialog and set the progressbar
            // on the frm to IsIndeterminate=true
            //THIS IS NOT WORKING
            this.Dispatcher.BeginInvoke (new Action(() =>
              {  ProgressDialog progressDialog = new ProgressDialog();
                progressDialog.SetIndeterminate(true);
            }));

             //this updates the main form OK
             this.Dispatcher.Invoke((MethodInvoker)delegate { tbLoadDgStat.Text = "Getting data templete from Database..."; });

        }
        else if (e.ProgressPercentage == 20)
        {

            this.Dispatcher.Invoke((MethodInvoker)delegate { tbLoadDgStat.Text = "Data template retrieved..."; });

        }
        else
        {

            if (e.ProgressPercentage % 10 == 0)
            {
                this.Dispatcher.Invoke((MethodInvoker)delegate { tbLoadDgStat.Text = "Adding Data..." + e.ProgressPercentage.ToString() + "%"; });
            }
        }

Por fim, o xaml para o formulário ProgressDialog e sua classe

<Window x:Class="Test_Read_CSV.ProgressDialog"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Progress Dialog" Height="115" Width="306" Name="ProgressPopup">
<Grid>
    <ProgressBar Height="31" HorizontalAlignment="Left" Margin="12,33,0,0" Name="progressBar1" VerticalAlignment="Top" Width="250" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="7,4,0,0" Name="tbEvent" VerticalAlignment="Top" Width="254" IsReadOnly="True" IsEnabled="False" />
</Grid>

classe

/// <summary>
/// Interaction logic for ProgressDialog.xaml
/// </summary>
public partial class ProgressDialog : Window
{
    public ProgressDialog()
    {
        WindowStartupLocation = WindowStartupLocation.CenterScreen;
        InitializeComponent();
    }

    public ProgressDialog(String Purpose)
    {
        InitializeComponent();
        tbEvent.Text = Purpose;
        WindowStartupLocation = WindowStartupLocation.CenterScreen;

    }
    public void UpdateProgress(int progress)
    {
        progressBar1.Dispatcher.BeginInvoke(
            new Action(() =>
            {
                progressBar1.Value = progress;
            }
        ));
    }

    public void SetIndeterminate(bool isIndeterminate)
    {
        progressBar1.Dispatcher.BeginInvoke(
            new Action(() =>
            {
                if (isIndeterminate)
                {
                    progressBar1.IsIndeterminate = true;
                }
                else
                {
                    progressBar1.IsIndeterminate = false;
                }
            }
        ));
    }
}

}

Eu li e fiz um número de tutorial sobre o trabalhador de fundo e até mesmo alguns em tópicos, mas não consigo obter o resultado que eu quero

A idéia é que eu tenho dois longos processos em que estou recebendo um clone datatable do meu bd remoto ou estou atualizando o db do meu aplicativo wpf (.net 4). Enquanto o processo está em execução, eu quero um controle de barra de progresso e atualizá-lo, pela óbvia razão de deixar claro que algum trabalho está acontecendo. Então eu fiz as rotinas de progresso do relatório usual no worker de plano de fundo e ele funciona .... No entanto, no meu thread dowork eu tenho esse comando

CHHoursDataProvider CH = new CHHoursDataProvider();
oTable = CH.CloneCHHours();

isso onde a comunicação com o db é e este comando leva uns bons 60 - 90 segundos em uma conexão remota vpn por isso mesmo se eu fizer isso

CHHoursDataProvider CH = new CHHoursDataProvider();
worker.ReportProgress((10));
oTable = CH.CloneCHHours();
worker.ReportProgress((20));

A janela principal ainda parece congelada e como ela caiu!

Então, tudo que eu quero fazer é no início da chamada para o trabalho de fundo é definir uma barra de progresso em execução e deixá-lo em execução até o final da tarefa. Isso é tudo que eu preciso fazer para terminar meu primeiro projeto e depois de três dias eu ainda não consigo entender isso!

Então eu tentei o seguinte

No progresso do bw alterado e na classe da janela principal

 this.progressBar2.IsIndeterminate = true;

No entanto, a animação não inicia até que o segmento Dowork seja concluído.

Em seguida, criei outro trabalhador de segundo plano para atualizar a barra de progresso2, que vinculado a um botão na janela principal estava ok, mas assim que tentei usá-lo do outro trabalhador de plano de fundo ou da classe da janela principal, não corri até o dowork thread tinha concluído no primeiro trabalhador de fundo

Então tentei seguir um método de invocação, mas REALMENTE me perdi com isso!

Então, alguém pode ajudar eu posso imaginar que é algo a ver com a segmentação e trabalhando no segmento errado, etc, mas o que eu faço sobre isso eu não tenho idéia.

Eu posso postar mais código conforme necessário

Ian

questionAnswers(1)

yourAnswerToTheQuestion