0

Firstly I am going to say hi, I am new there and in c# ;)

I am coding program that transfers translations between excel and SQLite files. It takes a while, so im trying to use progressbar, which is updated from transferring class (Imp/Exp) by Backgroundworker (in backgorundworker1_DoWork). I am trying to use this answer report progress backgroundworker from different class c# , but the bar updates only on startup and after transfer is done. Forms seems to work, I can move them and so on; I have tried the second solution, with an event, but it worked the same;

There is a code that may matter

The form class:

public partial class Form2 : Form
{

    private int process = 0;
    private ImpExp prgr;
    private bool _overwrite;
    public Form1 form1;
    public bool overwrite
    {
        get
        {
            return _overwrite;
        }
         private set
        {
            _overwrite = value;
            prgr.overwrite = _overwrite;
        }

    }
    public Form2(Form1 firstForm)
    {
        prgr = new ImpExp(firstForm.excPath, firstForm.excelCol, firstForm.dbPath, firstForm.otherLanguage, this);
        this.form1 = firstForm;
        InitializeComponent();
        backgroundWorker1.WorkerReportsProgress = true;
        backgroundWorker1.WorkerSupportsCancellation = false;
        this.Closing += new System.ComponentModel.CancelEventHandler(this.Form2_Closing);
        backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
        backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
        backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);

    }

    public void addColumn()
    {
        prgr.DB.addColumn();
    }

    private void importButton_Click(object sender, EventArgs e)
    {
            process = 1;
            if (!backgroundWorker1.IsBusy)
                backgroundWorker1.RunWorkerAsync();
    }

    private void exportButton_Click(object sender, EventArgs e)
    {

        if (!backgroundWorker1.IsBusy)
            backgroundWorker1.RunWorkerAsync();
        process = 2;
    }

    private void Form2_Load(object sender, EventArgs e)
    {
        YesRadioButton.Checked = true;
        AddLanguageForm addLanguageForm = new AddLanguageForm(this);
        if (!prgr.isReady)
        {
            Close();
        }

        else if (!prgr.DB.langGood)
            {

                addLanguageForm.ShowDialog();
                if (!addLanguageForm.yes)
                {
                    Close();
                }
            }
        Console.WriteLine("Form2 Opened");
        overwrite = YesRadioButton.Checked;
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
        label1.Text=(e.ProgressPercentage.ToString() + "%");

        Console.WriteLine("ProgressChanged " + e.ProgressPercentage);

    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        if (process == 1)   //import
        {
            base.Invoke((Action)delegate
            {
                cancelButton.Visible = false;

            });

            prgr.Import(sender as BackgroundWorker);
            process = 0;

            base.Invoke((Action)delegate
            {

                this.cancelButton.Text = "OK";
                cancelButton.Visible = true;
            });


        }
        else if (process == 2)  //export
        {
            base.Invoke((Action)delegate
            {
                cancelButton.Visible = false;
            });

            prgr.Export(sender as BackgroundWorker);
            process = 0;

            base.Invoke((Action)delegate
            {

                this.cancelButton.Text = "OK";
                cancelButton.Visible = true;
            });

        }

    }


    private void YesRadioButton_CheckedChanged(object sender, EventArgs e)
    {
        if (YesRadioButton.Checked == true)
        {
            NoRadioButton.Checked = false;
        }
        overwrite = YesRadioButton.Checked;
    }

    private void NoRadioButton_CheckedChanged(object sender, EventArgs e)
    {
        if (NoRadioButton.Checked == true)
        {
            YesRadioButton.Checked = false;
        }
        overwrite = YesRadioButton.Checked;

    }


}

Imp/Exp class from which im trying to actualize progressbar:

class ImpExp
{
    internal MyExcel excel;
    internal MySQLite DB;
    private Form2 form2;
    int firstRow, lastRow;
    internal bool overwrite;

    public bool isReady
    {
        get
            {
                if (excel.isReady && DB.isReady)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        set
            {
            }
    }
    public ImpExp(string excelPath, int excelCol, string dBPath, string dBCol, Form2 dad)
    {
        form2 = dad;
        excel = new MyExcel(excelPath, excelCol);
        DB = new MySQLite(dBPath,dBCol);
        firstRow = 6;
        lastRow=excel.lastRow;


    }
    public void Finish()
    {
        excel.close();
        DB.close();
    }
    public void Export(BackgroundWorker bw)
    {

        bw.WorkerSupportsCancellation = true;
        bw.WorkerReportsProgress = true;
        ExcelRow row = new ExcelRow();
        for (int i = firstRow; i <= excel.lastRow; i++)
        {

            excel.rowNumber = i;
            row = excel.actualRow();
            if (row.pl != null || row.other != null)
            DB.actualizeDB(row);
            Console.WriteLine(row.pl);
            Console.WriteLine(row.other);
            bw.ReportProgress(i/lastRow*100);

        }
        MessageBox.Show("Export finished");

    }
    public void Import(BackgroundWorker bw)
    {
        bw.WorkerSupportsCancellation = true;
        bw.WorkerReportsProgress = true;

        ExcelRow row = new ExcelRow();
        for (int i = firstRow; i <= excel.lastRow; i++)
        {
            string translationTemp;
            excel.rowNumber = i;
            row = excel.actualRow();
            if (overwrite)
            {
                if (row.pl != null)   //pl for Polish
                {
                    translationTemp=DB.translate(row.pl);
                    if (translationTemp != "TRANSLATION NOT FOUND!@#$%")       
                    {
                        string translationTemp2 = translationTemp.Replace(" ","");
                        if(translationTemp2 !="")       //Nie nadpisuj excela pustymi wpisami i spacjami
                        {
                            excel.saveTranslation(translationTemp, i);
                        }
                    }
                }
            }
            else
            {
                if (row.pl != null && (row.other == null || row.other == ""))
                {
                    translationTemp = DB.translate(row.pl);
                    if (translationTemp != "TRANSLATION NOT FOUND!@#$%")
                    {
                        excel.saveTranslation(translationTemp, i);
                    }
                }
            }
            bw.ReportProgress(i / lastRow * 100);



        }
        MessageBox.Show("Import finished");
    }


}
Community
  • 1
  • 1
  • what do you mean by "the bar actualizes only on startup and after transfer is done." ? – Nicholas Ellingson Aug 07 '15 at 13:28
  • @NicholasEllingson I mean that when I click importButton or exportButton, progressbar actualizes (for eg. if I change in code bw.ReportProgress(50); progressbar is half full after click) and after import or export progressbar is full. – Samuel.L.Jordan Aug 07 '15 at 14:10

1 Answers1

0

if you want to change propery of any control in Wfa. You have to use some sort of synchonizationContext. The easy one is.

    private void Change<T>(T obj, Action<T> action)
        where T : Control
    {
        if (obj.InvokeRequired)
        {
            obj.Invoke(
                new MethodInvoker(() => Change(obj, action)),
                new object[] { null });
        }
        else
        {
            action(obj);
        }
    }

when you need to change something in your control, for example label1. you have to do it like that

Change(label1, l => l.Text = a);

first argument is your control, second is what to do with your control. More information about InvokeRequired https://msdn.microsoft.com/en-us/library/ms171728(v=vs.85).aspx

Jan3Sobieski
  • 259
  • 1
  • 7
  • 16
  • Dzięki Sobieski. I put Change into Form2 class and form2.Change(form2.label1, l => l.Text = i / lastRow * 100 + "%"); into Imp/Exp instead of bw.ReportProgress(i/lastRow*100); but still doesn't work. As you see, i firstly try to change label1 text, but during debugging it has value: "'this.label1.Text' threw an exception of type 'Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException' " – Samuel.L.Jordan Aug 11 '15 at 09:51