Anonymní profil Shigy – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Anonymní profil Shigy – Programujte.comAnonymní profil Shigy – Programujte.com

 

Příspěvky odeslané z IP adresy 195.250.140.–

.NET › Problém s vlákny
20. 8. 2012   #161779

Díky ingiraxo za odkaz na video s tutoriálem. Upravil jsem podle něj kód, ale není to úplně to, co bych potřeboval.

Kód teď vypadá takto:

 public partial class Form1 : Form
    {
        private int max = 1000000;
        private int lastStav = 0;
        public Form1()
        {
            InitializeComponent();
            progressBar1.Minimum = 0;
            progressBar1.Maximum = max;
            progressBar1.Value = 0;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Rozjed to");
            Worker.RunWorkerAsync();
        }
       
        private void button2_Click(object sender, EventArgs e)
        {
            Watcher.RunWorkerAsync();
            MessageBox.Show("Zastav inkrementaci");
         }

        private void button3_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Opet bez");
            if (!Worker.IsBusy)
            {
                Worker.RunWorkerAsync();
            }
        }

        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {

            for (int i = 0; i <= max; i++ )
            {
                if (lastStav != 0)
                {
                    i = lastStav;
                }
                if (Worker.CancellationPending)
                {
                    lastStav = i;
                    break;
                }
                Worker.ReportProgress(i);
            }
        }

        private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }

        private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("Hotovo");
        }
        
        private void Watcher_DoWork(object sender, DoWorkEventArgs e)
        {
            Worker.CancelAsync();
        }

        
    }

BackGroundWorker skvěle posouvá progressBarem, ale tlačítka jsou jakoby zablokovaný a nejde žádné zmáčknout při běhu Workeru, takže nemůžu průběh nikdy pozastavit. Tlačítka jsou klikatelný až po doběhnutí cyklu. 

.NET › Problém s vlákny
20. 8. 2012   #161759

Dobrý den,

vytvářím prvně aplikaci s vlákny a nějak mi to nejde.    Potřebuju udělat aplikaci, kde poběží hlavní vlákno a akorát při spuštětí aplikace a nebo po uplynutí zadaného časového intervalu se spustí druhé vlákno (pracovní), které provede určitý úkol.  Potřebuju ale ještě, aby když probíhá pracovní vlákno a uživatel zmáčkne nějaké tlačítko, aby se pracovní vlákno zastavilo, hlavní vlákno zpracovalo požadavek uživatele a po jeho splnění se opět spustilo pracovní vlákno a dodělalo svůj úkol.

Jednoduchá aplikaci, na které si chci zprovoznit tuto funkčnost, než ji dám do skutečné aplikace. Pracovní vlákno se spouští pří startu a nebo po uplynutí času v Timeru1. Button2 simuluje požadavek od uživatele, má vyvolat pozastavení pracovního vlákna. Button3 simuluje splnění požadavku od uživatele a má opětovně spustit pracovní vlákno.

public partial class Form1 : Form
    {
        private int max = 100000000;
        Thread pracovni;
        
        public Form1()
        {
            InitializeComponent();
            progressBar1.Minimum = 0;
            progressBar1.Maximum = max;
            progressBar1.Value = 0;

            Thread.CurrentThread.Name = "hlavni";
            pracovni = new Thread(Inkrement);
            pracovni.Name = "pracovni";

            timer1.Interval = 1000;
            timer1.Start();
            
            pracovni.Start();
        }

        void Inkrement()
        {
            int i = 0;
            while (i != max)
            {
                i++;
                progressBar1.Increment(1);
                // InvalidOperationException - Cross-thread operation not valid: Control 'progressBar1' accessed 
                //from a thread other than the thread it was created on.
            }
            progressBar1.Value = 0;
            //restart
        }
        
        private void button2_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Zastav inkrementaci");
            pracovni.Join();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Opet bez");
            pracovni.Start();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            MessageBox.Show("Samorozjezd");
            pracovni.Start();
        }
    }

Problém je v metodě Inkrement. Když dojde k úpravě hodnoty Value progressBar1, vyskočí vyjímka uvedená v zakomentované části pod progressBar1.Increment(1);

Chápu, že nemůžu z pracovního vlákna volat objekt vytvořený v hlavním vláknu. Zkoušel jsem kód upravit s pomocí delegátů, ale poté program funguje tak, že proběhne Inkrement až do konce a nejde stisknout žádné tlačítko a Inkrementaci přerušit.    Ještě jsem musel odstranit Timer, protože pak mi jen vyskakovalo okno, že došlo k samospuštění a program skončil vyjimkou, když chtěl upravovat Value progressBar1.

 Kód s delegátem:

public partial class Form1 : Form
    {
        private int max = 1000000;
        Thread pracovni;
        
        public Form1()
        {
            InitializeComponent();
            progressBar1.Minimum = 0;
            progressBar1.Maximum = max;
            progressBar1.Value = 0;

            Thread.CurrentThread.Name = "hlavni";
            pracovni = new Thread(new ThreadStart(Inkrement));
            pracovni.Name = "pracovni";
            
            pracovni.Start();
        }
        protected delegate void SetIntDelegate(int cislo);
        protected void SetInt(int cislo)
        {
            progressBar1.Value=cislo;
        }
        void Inkrement()
        {
            lock (this)
            {
                int i = 0;
                while (i != max)
                {
                    i++;
                    BeginInvoke(new SetIntDelegate(SetInt), new object[] { i });
                }
            }
            progressBar1.Value = 0;
        }
        
        private void button2_Click(object sender, EventArgs e)
        {
            if (pracovni.ThreadState == ThreadState.Running)
            {
                MessageBox.Show("Zastav inkrementaci");
                pracovni.Join();
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (pracovni.ThreadState == ThreadState.WaitSleepJoin)
            {
                MessageBox.Show("Opet bez");
                pracovni.Start();
            }
        }
    }

Byl bych moc vděčný za radu, jak to napsat, aby to fungovalo podle mých potřeb.  Děkuji moc

A ještě bych se chtěl zeptat, jestli je dobrý způsob pozastavení pracovního vlákna metodou pracovni.Join();?

Děkuji moc

Shigy
Java › Prosím o radu (předávání par…
7. 6. 2008   #76115

Chtěl bych se zeptat, jestli je možné v Javě nějak předávat primintivní datové typy odkazem, potebuju hlavně string... Jsem zvyklý programovat v Delphi a při převodu několika algoritmů do javy sem narazil na tento problém... Jediné co mě napadlo je nák to obejít polem, ale myslím že by mohlo být i nějaké standartní řešení...?

 

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032021 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý