Как исправить ошибку «имя« k »не существует в текущем контексте»? - PullRequest
0 голосов
/ 18 апреля 2019

Я получаю ошибку System.IndexOutOfRangeException только при нормальном запуске решения, но все нормально при переходе через весь цикл.

a busy cat

Я пытался поймать исключение, но без радости.

private void button1_Click(object sender, EventArgs e)
        {
            for (int j = 0; j < jobs.Length; j++)
            {
                if (jobs[j].JobID == false)
                {
                    for (int k = 0; k < threads.Length; k++)
                    {
                        if (threads[k] != null)
                        {
                            if (!(threads[k].ThreadState == ThreadState.Stopped) | !(threads[k].ThreadState == ThreadState.Unstarted))
                            {
                                continue;
                            }
                        }

                        try
                        {
                            threads[k] = new Thread(() => CountUp("ftp://ftp.net" + jobs[j].FTPFolder, HomePath + jobs[j].localFolder, j));
                            threads[k].Name = "Thread " + j + "¦ ID: " + threads[k].ManagedThreadId.ToString();
                            jobs[j].JobID = true;
                            //threads[k].Start();
                            break;
                        }
                        catch (Exception exception)
                        {
                            Console.WriteLine(exception);
                            throw;
                        }

                    }
                }
            }
            StartThreads();
        }

Я ожидаю, что все потоки в массиве threads [] будут инициализированы, если задание []. JobID имеет значение false.

Ниже приведен метод CountUp ():

        private void CountUp(string ftppath,string localFile, int jobsID)
        {
            //string conf="";
            NumberThreads++;
            //string ftpPath = "ftp://ftp.Rxsystems.net" + conf.Split('¦')[1];
            //string downloadPath = HomePath + conf.Split('¦')[0] + "\\";

            string ftpPath = ftppath;
            string downloadPath = localFile;

            List<string> MSI = new List<string>(KD.FTP.Class.ListFiles(ftpPath,
                FTPuser, FTPpass));

            if (MSI.Count > 0)
            {
                KD.File.Class.Logger(Thread.CurrentThread.Name + ", " + MSI.Count + " Files in " + ftpPath, CurDir + "\\log.txt");

                this.textBox1.AppendText(Thread.CurrentThread.Name + ", " + MSI.Count + " Files in " + ftpPath);
                //this.textBox1.AppendText("\n\r");
                int count = 0;
                foreach (string ftpFile in MSI)
                {
                    KD.FTP.Class.Download(ftpPath + ftpFile,downloadPath + "\\" + ftpFile, FTPuser,FTPpass);
                    count++;
                    KD.File.Class.Logger(Thread.CurrentThread.Name + ", " + "Downloaded " + count + "/" + MSI.Count + " Files - " + ftpFile, CurDir + "\\log.txt");
                    this.textBox1.AppendText(Thread.CurrentThread.Name + ", " + "Downloaded " + count + "/" + MSI.Count + " Files - " + ftpFile);
                    //this.textBox1.AppendText("\n\r");
                }
            }


            NumberThreads--;
            jobs[jobsID].JobID = false;
        }

Ниже приведены инициализации потоков [] и заданий []:

private void Form1_Load(object sender, EventArgs e)
        {
            Form1.CheckForIllegalCrossThreadCalls = false;

            if (File.Exists(CurDir + "\\FTPpaths.config"))
            {
                foreach (string line in File.ReadAllLines(CurDir + "\\FTPpaths.config"))
                {
                    if (!string.IsNullOrEmpty(line))
                    {
                        ConfigPaths.Add(line.Split('¦')[0] + "¦" + line.Split('¦')[1]);
                    }
                }

                if (ConfigPaths.Count > 0)
                {
                    jobs = new Jobs[ConfigPaths.Count];

                    for (int j = 0; j < ConfigPaths.Count; j++)
                    {
                        jobs[j] = new Jobs();
                        jobs[j].FTPFolder = ConfigPaths[j].Split('¦')[1];
                        jobs[j].localFolder = ConfigPaths[j].Split('¦')[0];
                        jobs[j].JobID = false;
                    }

                    threads = new Thread[jobs.Length];

                }


                timer1.Enabled = true;
            }
            else
            {
                Application.Exit();
            }
        }

1 Ответ

2 голосов
/ 18 апреля 2019

Из того, что я вижу, проблема в переменной j, которая захватывается из замыкания в делегат, передаваемый в new Thread.Это хорошо известная проблема, когда фактическое выполнение делегата ссылается на переменную в состоянии после выполнения цикла, поэтому она должна содержать значение jobs.Length, выходящее за пределы допустимого диапазона.Для исправления необходимо ввести локальную переменную внутри цикла для копирования значения j, а затем использовать эту переменную вместо j в качестве индекса jobs внутри делегата, переданного конструктору Thread:

try
{
    var jobIdx = j;
    threads[k] = new Thread(() => CountUp("ftp://ftp.net" + jobs[jobIdx].FTPFolder, HomePath + jobs[jobIdx].localFolder, jobIdx));
    ...
    // other stuff

}
catch (Exception exception)
{
    Console.WriteLine(exception);
    throw;
}
...