Dwa wątki na raz

0

Witam

Mam problem bo chcę aby dwa wątki działały na raz,a na razie mam że jeden działa po drugim i na zmianę. Jeden trwa 3 sekundy, drugi 15 sekund i chcę żeby ten pierwszy wykonał się 5 razy i dopiero wtedy tamten. Czyli chodzi o to żeby działały dwa na raz, a nie każdy po sobie.

Kod:

 while(1<2)
            {
                Thread watek = new Thread(doreczenie_listu);
            watek.Start();
            Thread.Sleep(TimeSpan.FromSeconds(3));

            Thread oproznianie = new Thread(oproznij_skrzynke);
            oproznianie.Start();
            Thread.Sleep(TimeSpan.FromSeconds(15));
            }
0

Robiąc tutaj

Thread.Sleep(TimeSpan.FromSeconds(3));

usypiasz główny wątek, więc siłą rzeczy będą się one wykonywały jeden po drugim, bo uruchamiasz pierwszy wątek, potem usypiasz GŁÓWNY wątek na 3 sekundy i dopiero następnie odpalasz drugi wątek i znowu usypiasz GŁÓWNY na 15 sekund. W momencie jak usypiasz główny wątek to wstrzymujesz pracę całego programu, dlatego jest jak jest :)

Jeśli chcesz uśpić ten wątek odpowiedzialny za doręczenie listu to musisz w metodzie doreczenie_listu go uśpić a nie tutaj.

0

ale jak dam tą linjkę z usypianiem w tych dwóch metodach na końcu to one wcale nie czekają tych 3 i 15 sekund, tylko wykonują sie tak szybko i wywala program out of memory, bo tak już próbowałem

Thread.Sleep(TimeSpan.FromSeconds(20));

Cały kod wygląda teraz tak:

class Program
    {
        public static int[] skrzynka = new int[16];  // 16 skrzynek

       

        static void Main(string[] args)
        {
            for (int i = 0; i < 16; i++)  
            {
                skrzynka[i] = 0; // 0 oznacza pusta skrzynke
            }

            while(1<2)
            {
                Thread watek = new Thread(doreczenie_listu);
            watek.Start();
            

            Thread oproznianie = new Thread(oproznij_skrzynke);
            oproznianie.Start();
            
            }
        }


        static void doreczenie_listu()
        {

           
            Random rd = new Random();
            int x = rd.Next(1,16);

            if (skrzynka[x] == 0)
            {
                Console.WriteLine("Doreczono list do skrzynki: " + x);
                skrzynka[x] = 1;
            }
            else
            {
                Console.WriteLine("Skrzynka: "+x+" pełna. List ląduje w koszu");
            }

            Thread.Sleep(TimeSpan.FromSeconds(3));

        }

        static void oproznij_skrzynke()
        {

            
            Console.WriteLine("Oprożnianie skrzynek!!!");
            for (int i = 0; i < 16; i++)
            {
                skrzynka[i] = 0;

            }

            Thread.Sleep(TimeSpan.FromSeconds(20));
        }
    }
0

Ogólnie warunek w while zamiast 1<2 zastąp while(true)- wygląda bardziej naturalnie.

Ależ owszem, te Sleepy usypiają wątki, tylko w momencie jak jeden z nich jest uśpiony na 3 sekundy to powstaje już cała masa innych wątków i to Ci zapycha pamięć. Wątki w while tworzone są co chwile i po chwili jest ich tyle, że pamięć komputera nie jest w stanie tego ogarnąć i najzwyczajniej w świecie brakuje jej miejsca. Powinieneś stworzyć JEDEN raz wątek i on powinien wykonywać doręczenie listu cały czas. Czyli zrób jakąś pętlę nieskończoną w doręczenie_listu a w konstruktorze main nie rób żadnej pętli tylko raz wystartuj każdy z wątków. To samo zrób w metodzie oproznij_skrzynke i powinieneś uzyskać zadowalający Cię efekt :)

0

dobra dzięki to działa, ale jeszcze mi powiedz jak zrobić żeby mieć tablicę wątków i każda wywołuje funkcję
Thread[] oproznianie = new Thread(oproznij_skrzynke)[]; - bo takie coś nie działa

Bo chcę np. żeby 5 skrzynek zostało opróżnionych po jakimś czasie w różnych wątkach.

0

No nie działa bo nie podałeś rozmiaru tablicy. Pierw takie coś, deklarujesz ilość elementów:

Thread[] oproznianie = new Thread[5];

No a później na rzecz każdego elementu startujesz to co tam sobie wymarzysz.

0

No działa to tylko że znowu jest problem bo każdy wątek ma wybrać inną skrzynkę do opróżnienia, a teraz każdy wątek chce opróżnić tą samą skrzynkę.

Screen: http://screenshooter.net/100395200/ulkqbru

 

class Program
    {
        public static int[] skrzynka = new int[16];  // 16 skrzynek

       

        static void Main(string[] args)
        {
            for (int i = 0; i < 16; i++)  
            {
                skrzynka[i] = 0; // 0 oznacza pusta skrzynke
            }

           
                Thread watek = new Thread(doreczenie_listu);
            watek.Start();

            Thread[] oproznianie = new Thread[5];

            for (int j = 0; j < 5; j++)
            {
                oproznianie[j] = new Thread(oproznij_skrzynke);
                oproznianie[j].Start();
            }
            
        }


        static void doreczenie_listu()
        {
            while (1 < 2)
            {

                Random rd = new Random();
                int x = rd.Next(1, 16);

                if (skrzynka[x-1] == 0)
                {
                    Console.WriteLine("Doreczono list do skrzynki: " + x);
                    skrzynka[x-1] = 1;
                }
                else
                {
                    Console.WriteLine("Skrzynka: " + x + " pełna. List ląduje w koszu");
                }
                Thread.Sleep(TimeSpan.FromSeconds(3));
            }

        }

        static void oproznij_skrzynke()
        {
            while (1 < 2)
            {
                Random f = new Random();
                int y = f.Next(1,16);

                Console.WriteLine("Wlascicel "+y+" oprożniania skrzynkę!!!");
                
                    skrzynka[y] = 0;

               

                Thread.Sleep(TimeSpan.FromSeconds(20));
            }
        }
    }

0

No w takim razie musisz metodę oproznij_skrzenke wywoływać z parametrem, którym będzie numer skrzynki do opróżnienia. Żeby wywołać metodę z parametrem dla wątku musisz użyć wyrażenia lambda. Tutaj masz przykład, który możesz zastosować u siebie.

http://stackoverflow.com/questions/3360555/how-to-pass-parameters-to-threadstart-method-in-thread

0

próbowałem to trochę inaczej zrobić ale coś z tym randomem jest nie tak. Niby lepiej ale lepiej by było 5 na raz.

zmieniłem metode do oprozniania tak:

Screen teraz: http://screenshooter.net/100395200/yjtbpkd

 

static void oproznij_skrzynke()
        {
            int h = 0;
            while (true)
            {
                Random f = new Random();
                int y = f.Next(0,16);
                h = 0;
                while (h == 0)
                {
                    if (skrzynka[y] == 0)
                    {
                        y = f.Next(0, 16);
                    }
                    else
                    {
                        Console.WriteLine("Wlascicel " + (y + 1) + " oprożniania skrzynkę!!!");

                        skrzynka[y] = 0;
                        h = 1;
                    }
                }
               

                Thread.Sleep(TimeSpan.FromSeconds(20));
            }
        }


0

Wywal

Random f = new Random();

przed while, wtedy będziesz miał losowe liczby

0

dałem coś takiego żeby parametrem było j i też d*pa

 

  for (int j = 0; j < 5; j++)
            {
                oproznianie[j] = new Thread(delegate() { oproznij_skrzynke(j); });
                oproznianie[j].Start();
            }

tak samo

0

dobra zrobiłem, dzięki wielkie za pomoc

1 użytkowników online, w tym zalogowanych: 0, gości: 1