[c#] ilosc liczb parzystych na liscie z wykorzystanim watkow

0

Mam listę zawierającą losowe liczby całkowite. Chciałbym nauczyć się korzystać z wątków i przy okazji sprawdzić czas w jakim ustalana jest liczba elementów parzystych bez wykorzystania wątków i z wykorzystaniem wątków(z wykorzystaniem wątków to robię tak, że jeden wątek sprawdza co drugi element listy sprawdzając czy jest parzysty zaczynając od indeksu=0, a drugi watek także sprawdza co drugi element listy zaczynając od indeksu=1). I chciałem żeby jeden wątek zwracał ile znalazł elementów parzystych i drugi wątek żeby zwracał ile znalazł elementów parzystych i następnie bym zsumował otrzymane wartości i otrzymał łączną ilość elementów parzystych w liście z wykorzystaniem wątków. Ale zdaje się, że metody wątków nie mogą zwracać wartości więc nie wiem jak to zrobić :( Dodam jeszcze, że chciałbym to zrobić korzystając z BEZPOŚREDNIEGO używania wątków bez żadnych rzeczy, które występują tylko w c# jak np. delegacje asynchroniczne, żeby potem łatwo było przerobić ten kod do wykorzystania w innych językach. Jak to mogę zrobić skoro metody wątków nie mogą zwracać wartości ?

Program wygląda w ten sposób:

namespace ConsoleApplication1
{
    class Program
    {

        static void Main(string[] args)
        {
            List<int> lista = new List<int>();
            const int rozmiar = 50000000;
            Random losowa = new Random();

            for (int i=0; i < rozmiar; i++)
            {
                lista.Add(losowa.Next(10000));
            }



            DateTime startTime1 = DateTime.Now;
            int a = 0;
            for (int i = 0; i < lista.Count(); i++)
            {
                if (lista[i] % 2 == 0) a++;
            }

            DateTime stopTime1 = DateTime.Now;
            TimeSpan roznica1 = stopTime1 - startTime1;
            Console.WriteLine("Ilosc elementow parzystych bez watkow: " + a);
            Console.WriteLine("Czas wykonania bez watkow w ms: " + roznica1.TotalMilliseconds);




            DateTime startTime2 = DateTime.Now;

            Thread t1 = new Thread(new ParameterizedThreadStart(watek1));
            Thread t2 = new Thread(new ParameterizedThreadStart(watek2));

            t1.Start(lista);
            t2.Start(lista);


         
            if (t1.IsAlive) .
            {
                t1.Abort();
            }
            if (t2.IsAlive)
            {
                t2.Abort();
            }


            DateTime stopTime2 = DateTime.Now;
            TimeSpan roznica2 = stopTime2 - startTime2;
            Console.WriteLine("Czas wykonania z watkami w ms: " + roznica2.TotalMilliseconds);


            Console.Read();
        }



        static private void watek1(object listaa)
        {

            List<int> lista = (List<int>)listaa;


            int a=0;
            for (int i = 0; i < lista.Count(); i = i + 2)
            {
                if (lista[i] % 2 == 0) a++;
                Thread.Sleep(1);
            }

        }

        static private void watek2(object listaa)
        {

            List<int> lista = (List<int>)listaa;
           
           
            int b = 0;
            for (int i = 1; i < lista.Count(); i = i + 2)
            {
                if (lista[i] % 2 == 0) b++;
                Thread.Sleep(1);
            }

        }

    }
}
0

if (t1.IsAlive) .
{
t1.Abort();
}
if (t2.IsAlive)
{
t2.Abort();
}
Tu chyba nie za bardzo wiesz co zrobiłeś ;) Wątek główny musi poczekać na wątki pracujące aż same skończą działanie:

t1.Join(); //czekamy na pierwszy wątek
t2.Join(); //czekamy na drugi wątek 

Co do zwracania wartości - zadeklaruj statyczne 2 pola typu int wewnątrz klasy Program i ich użyj.

I tak w ogóle to nie potrzebnie pisałeś 2 razy prawie taką samą procedurę. Obydwa wątki mogą korzystać z jednej i tej samej. Musisz tylko przekazać wątkowi przy jego tworzeniu od jakiej liczby szukanie ma zacząć. Zrobisz to w taki sam sposób jak przekazałeś listę, a samej listy nie przekazuj parametrem tylko zrób ją jako statyczne pole klasy Program.

0

Częściowo poprawiłem wg Twoich wskazówek - tylko teraz zmieniłem, że zamiast ilości liczb parzystych jest liczona ilość liczb pierwszych - bo to o wiele bardziej pracochłonne więc lepiej widać różnice w czasie między wykorzystaniem do tego wątków i bez wykorzystania wątków. Czas z wykorzystaniem wątków do tych obliczeń na procesorze dwurdzeniowym Core 2 Duo jest dwa razy krótszy niż bez wykorzystania wątków a obciążenie rdzeni procesora = 100%. :D :D
Tylko na jakimś forum czytałem jeszcze, że w metodach wątków - u mnie w watek1() i watek2() powinno się używać Thread.Sleep(1) żeby w ten sposób dać podziałać drugiemu wątkowi - ale jak to umieszcze w metodach wątków to ilość liczb pierwszych jest liczona KILKADZIESIAT razy dłużej oraz wykorzystanie procesora wynosi coś koło 4% !! - praktycznie nie da się doczekać na zakończenie liczenia - myślę, że to dlatego iż co 1 ms bieżący wątek jest usypiany i działa drugi wątek i tak w kółko, więc to jest chyba bez sensu z tym Thread.Sleep() w metodach wątków ??

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;


namespace ConsoleApplication1
{
    class Program
    {

        static void Main(string[] args)
        {

            klasa k = new klasa();


            List<int> lista = new List<int>();
            const int rozmiar = 5000000;
            Random losowa = new Random();

            for (int i=0; i < rozmiar; i++)
            {
                lista.Add(losowa.Next(10000));
            }


            Console.WriteLine("Wcisnij klawisz by poznac ilosc liczb pierwszych bez uzycia watkow");
            Console.ReadKey();

            DateTime startTime1 = DateTime.Now;



            int a = 0;
            int liczba;

            for (int i = 0; i < lista.Count(); i++)
            {
                liczba = lista[i];
                for (int x = 2; x < liczba; x++)
                {
                    if (liczba % x == 0)
                    {
                        a++;
                        break;
                    }
                }
            }
            
            Console.WriteLine("Ilosc liczb pierwszych bez watkow: " + a);
            DateTime stopTime1 = DateTime.Now;
            TimeSpan roznica1 = stopTime1 - startTime1;
            Console.WriteLine("Czas wykonania bez watkow w ms: " + roznica1.TotalMilliseconds);
            Console.WriteLine();




            Console.WriteLine("Wcisnij klawisz by poznac ilosc liczb pierwszych z uzyciem watkow");
            Console.ReadKey();

            DateTime startTime2 = DateTime.Now;

            Thread t1 = new Thread(new ParameterizedThreadStart(k.watek1)); 

            Thread t2 = new Thread(new ParameterizedThreadStart(k.watek2));

            t1.Start(lista);
            t2.Start(lista);

            

            t1.Join();
            t2.Join();

            int liczba1 = k.zwroc1;
            int liczba2 = k.zwroc2;
            int suma = liczba1 + liczba2;
            Console.WriteLine("Ilosc liczb pierwszych z watkami: " + suma);
            DateTime stopTime2 = DateTime.Now;
            TimeSpan roznica2 = stopTime2 - startTime2;
            Console.WriteLine("Czas wykonania z watkami w ms: " + roznica2.TotalMilliseconds);




            Console.ReadKey();
        }



        public class klasa
        {
            private int wartosc1;
            private int wartosc2;


            
            public void watek1(object listaa)
            {
                List<int> lista = (List<int>)listaa;


                int a = 0;
                int liczba;

                for (int i = 0; i < lista.Count(); i = i + 2)
                {
                    liczba = lista[i];
                    for (int x = 2; x < liczba; x++)
                    {
                        if (liczba % x == 0)
                        {
                            a++;
                            break;
                        }
                    }

                }    
                wartosc1 = a;
            }


            public int zwroc1
            {
                get
                {
                    return wartosc1;
                }
            }


            public void watek2(object listaa)
            {
                List<int> lista = (List<int>)listaa;


                int b = 0;
                int liczba;

                for (int i = 1; i < lista.Count(); i = i + 2)
                {
                    liczba = lista[i];
                    for (int x = 2; x < liczba; x++)
                    {
                        if (liczba % x == 0)
                        {
                            b++;
                            break;
                        }
                    }
                }

                wartosc2 = b;
            }

            public int zwroc2 
            {
                get
                {
                    return wartosc2;
                }
            }

        }

    }
}
0

Odpisałem Ci już na CodeGuru, tylko że tam zdaje się używasz delegatów, nie czystych wątków.
I zwróciłem uwagę na kilka pierdół, jak chociażby to, że wcale nie wyszukujesz liczb pierwszych ;]

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