LOCK, blokowanie wielu metod

0

Witam
Poszukuje rozwiązania, do programu w którym uruchamiane jest jednocześnie kilka wątków, pozwalające zblokować dostęp do określonych metod w momencie kiedy jeden z wątków wywoła którąś z nich.
Do tej pory wymyśliłem jedno rozwiązanie które przedstawiam poniżej ale jak dla mnie jest ono niewygodne i nieestetyczne.
Proszę was o skomentowanie co sądzicie o tym rozwiązaniu i jeśli ktoś ma lepszy pomysł to proszę o jego przedstawienie :).

public partial class Form1 : Form
{
    private void button1_Click(object sender, EventArgs e)
    {
        Thread _watek1 = new Thread(new ThreadStart(PetlaW1));
        Thread _watek2 = new Thread(new ThreadStart(PetlaW2));
        _watek1.Start();
        _watek2.Start();
    }
    public void PetlaW1()
    {
        Thread _currThread = Thread.CurrentThread;
        for (int i = 0; i < 1000; i++)
        {
            Klasa x = new Klasa();
            lock (this)
            {
               x.Lista(1, "", "");
            }
        }
        _currThread.Abort();
    }
    public void PetlaW2()
    {
        Thread _currThread = Thread.CurrentThread;
        for (int i = 0; i < 1000; i++)
        {
            Klasa x = new Klasa();
            lock (this)
            {
               x.Lista(2, "zadanie", "10");
            }
        }
        _currThread.Abort();
    }

class Klasa
{
    public int Lista(int _co, string _dane1, string _dane2)
    {
        switch (_co)
        {
            case 1:
                {
                    return PoliczIloscWpisow();
                }
            case 2:
                {
                    return DodajWpis(_dane1, _dane2);
                }
        }
        return -1;
    }
    private int PoliczIloscWpisow()
    {
            //  policzenie ilości wpisów
            return _iloscWpisow;
    }
    private int DodajWpis(string _nrZad, string _opis)
    {
            //  dodanie danych do pliku
            return -1;
    }

}

Oczywiście to co jest tu napisane działa ale np metoda DodajWpis zwraca inta -1 tylko dlatego że wymaga tego metoda Lista a Lista zwraca inta bo zawiera w sobie wywołanie metody PoliczIloscWpisow której zadaniem jest właśnie zwrócenie takowej wartości.
Przedstawione rozwiązanie działa ale jak dla mnie to typowy gniot :( więc jeśli ma ktoś lepsze rozwiązanie to proszę o pomoc :)
pozdro
0

nie jestem pewien patrząc na kod co chcesz osiągnąć - Twój kod zapewnia, że dostęp do metody Klasa.Lista dla każdego obiektu typu Klasa ma tylko jeden wątek, ale każdy klient korzystający z tych obiektów musi sam zadbać o synchronizację.

Jeśli o to właśnie chodzi (a nie np. o synchronizację dostępu do metody na poziomie jednego, konkretnego obiektu), to użyłbym trochę innego rozwiązania:

// comment directive below to see the difference
#define LOCK_ENABLED

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;


namespace _p_115485
{
    public enum MethodID
    {
        MethodOne,
        MethodTwo
    }

    public class IamSyncAtMethodForAllInstances
    {
        private static object syncObject = new object();

        public void MethodRouter(MethodID methodID)
        {
#if LOCK_ENABLED
            lock (syncObject)
#endif
            {
                switch (methodID)
                {
                    case MethodID.MethodOne:
                        // do something
                        Form1.AddListItem();                        
                        Thread.Sleep(533);
                        break;
                    case MethodID.MethodTwo:
                        // do something else
                        Form1.Count();                        
                        Thread.Sleep(300);
                        break;
                }
            }
        }
    }

    public partial class Form1 : Form
    {
        Thread  _threadNewEntry;
        Thread  _threadCounter;

        static Form1 form1 = null;

        /* this form has also two listboxes named:
         * - lbEntries
         * - lbCount
         */

        delegate int AddListItemDelegate(string item);

        public static void AddListItem()
        {
            // seems complicated but it is only cross-thread marshalling
            // to execute delegate on thread owning the control
            form1.lbEntries.Invoke(new AddListItemDelegate(form1.lbEntries.Items.Add),
                            new object[] { DateTime.Now.ToLongTimeString() });
        }

        public static void Count()
        {
            // seems complicated but it is only cross-thread marshalling
            // to execute delegate on thread owning the control
            form1.lbCount.Invoke(new AddListItemDelegate(form1.lbCount.Items.Add),
                            new object[] {
                                string.Format("Number of entries in list is {0}.", form1.lbEntries.Items.Count)});
        }


        private void AddEntry()
        {
            try
            {
                for (int i = 0; i < 5; i++)
                {                     
                    new IamSyncAtMethodForAllInstances().MethodRouter(MethodID.MethodOne);
                }
            }
            catch (ThreadAbortException e)
            {
            }
            finally
            {
                _threadNewEntry = null;
            }
        }

        private void CountEntries()
        {
            try
            {
                for (int i = 0; i < 5; i++)
                {
                    new IamSyncAtMethodForAllInstances().MethodRouter(MethodID.MethodTwo);
                }
            }
            catch (ThreadAbortException e)
            {
            }
            finally
            {
                _threadCounter = null;
            }
        }


        public Form1()
        {
            InitializeComponent();

            form1 = this;
        }

        private void btnStartStop_Click(object sender, EventArgs e)
        {
            if (null == _threadNewEntry)
            {
                _threadNewEntry = new Thread(new ThreadStart(AddEntry));
                _threadCounter = new Thread(new ThreadStart(CountEntries));

                _threadNewEntry.Start();
                _threadCounter.Start();
            }
            else
            {
                _threadCounter.Abort();
                _threadNewEntry.Abort();
            }

        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            lbCount.Items.Clear();
            lbEntries.Items.Clear();
        }

        
    }
}

btw, słowo kluczowe lock przekłada się na wykorzystanie metod Enter i Exit klasy Monitor z System.Threading

0

Serdeczne dzięki, prawdopodobnie o to chodziło ale jeszcze trochę czasu mi zejdzie zanim w 100% zrozumiem ten kod, jeszcze raz dzięki za odp

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