Values “resetting” back to zero after Task is comp

2019-09-08 16:14发布

问题:

This is my function, it returns a struct with the number of successful commands, the number of the ones with errors and also the total of both and also the file path from wich they are being exectued in a Iprogress interface.

   public void ExecuteCommands(string Directories, CdpsiUpdateSql Updater, CdpsiUpdateSqlparser parser, string Log, IProgress<Result> progress)
        {
            Result FinalResult = new Result();
            int totalWithErrors = 0;
            int totalSuccess = 0;
            string[] numArray1 = new string[3];
            List<string> list = ((IEnumerable<string>)Directory.GetFiles(Directories, "*.sql", SearchOption.TopDirectoryOnly)).Select(f =>
            {
                string[] strArray = Path.GetFileName(f).Split('_');
                int result;
                if (strArray.Length < 1 || !int.TryParse(strArray[0], out result))
                    result = -1;
                var data = new
                {
                    File = f,
                    Version = result
                };
                return data;
            }).Where(f => f.Version > -1).OrderBy(f => f.Version).Select(f => f.File).ToList<string>();
            foreach (string str in list)
            {
                int[] numArray2 = this.ExecuteCommand(parser.Parser(str), Updater, str, Log);
                int Succcesses = numArray2[0];
                int Errors = numArray2[1];
                //totalWithErrors += Errors;
                //totalSuccess += Succcesses;

                FinalResult.File = str;
                FinalResult.Errors = Errors;
                FinalResult.Successes = Errors;
                //FinalResult.TotalWithErrors = totalWithErrors;
                //FinalResult.totalSuccess = totalSuccess;


                progress.Report(FinalResult);
            }
        }

In my main code I call the function like this:

foreach (var ConnectionString in ConnectionStrings)
        {
            connection = new OracleConnection(ConnectionString);
            using (CdpsiUpdateSql NewUpdater = new CdpsiUpdateSql(connection))
            {
                labelBDver.Text = Global.VersaoBd = NewUpdater.LookUp("GGDSC", "APPLCONFIG", "GGCOD = 'APP_NAME'");
                lbVersao.Text = "Versão: " + Global.NovaVersao;
                CpdisUpdateScripts Scripts = new CpdisUpdateScripts();
                CdpsiUpdateSqlparser Parser = new CdpsiUpdateSqlparser();
                var progressHandler = new Progress<CpdisUpdateScripts.Result>(result =>
                {
                    textBox1.Text = result.File;
                    //Global.TotalExecCerros = result.TotalWithErrors;
                    //Global.TotalExecSuccessfull = result.totalSuccess;
                    Global.TotalExecCerros += result.Errors;
                    Global.TotalExecSuccessfull += result.Successes;
                    labelErrorCommandCnt.Text = result.Errors.ToString();
                    labelSuccessfulCnt.Text = result.Successes.ToString();
                    Refresh();

                });
                IProgress<CpdisUpdateScripts.Result> progress = progressHandler;
                Task MyTask = Task.Run(() =>
                {

                    Scripts.ExecuteCommands(Global.Update + @"\scripts", NewUpdater, Parser,
                        Global.Update + @"\scripts", progress);

                });

            }
        }

On the handler, the values that are passed to the labels are correct, the labels recive the correct values and the Global.Cerros and Global.TotalExecSuccessfull = result.totalSuccess; also recieve the correct number of errors, but when the foreach finishes both are 0. I can't understand why this is happening.

回答1:

Your problem is with your IProgress.Report(FinalResult). You need to create a new copy of the Result object everytime when passing it to IProgress.Report method.

So to solve your problem, you need to change you code as follows:

public void ExecuteCommands(string Directories, CdpsiUpdateSql Updater, CdpsiUpdateSqlparser parser, string Log, IProgress<Result> progress)
{
    //Remove this line
    //Result FinalResult = new Result();

    //... your code as is... bla bla bla

    foreach (string str in list)
    {
        int[] numArray2 = this.ExecuteCommand(parser.Parser(str), Updater, str, Log);
        int Succcesses = numArray2[0];
        int Errors = numArray2[1];

        //new line
        Result FinalResult = new Result();
        FinalResult.File = str;
        FinalResult.Errors = Errors;
        FinalResult.Successes = Errors;

        progress.Report(FinalResult);

    }
}