Laden...

ReaderWriterLockSlim: Lesesperre wird nicht aktiv

Erstellt von dahaack vor 12 Jahren Letzter Beitrag vor 12 Jahren 628 Views
Thema geschlossen
D
dahaack Themenstarter:in
47 Beiträge seit 2011
vor 12 Jahren
ReaderWriterLockSlim: Lesesperre wird nicht aktiv

Hallo,

ich möchte den Lese-Zugriff auf die Daten einer Klasse mit der ReaderWriterLockSlim-Klasse sperren.

Um die Sperrung zu Testen habe ich mir ein kleines Programm geschrieben. In der MyProcessClass.ProcessMethod() findet eine lange Schleife statt, die das Attribut progress der Klasse ändert. Diese Methode wird von einem Thread aus der Methode StartProcessThread() gestartet.

Über den Button1 starte ich den Thread. Zunächst wird die lange Schleife durchlaufen, die das Attribut progress aktualisiert. Danach soll das Lesen der Attribute gesperrt werden. Nach dem Sperren wird noch einmal eine lange Schleife durchlaufen und das Attribut aktualisiert. An einem Progressbar der Windowsform (wird durch Timer aktualisert) kann ich aber erkennen, dass die Lesesperre nicht eingetreten ist. Der Progressbar läuft wie in der ersten Sperre von 0 langsam nach 100. (Über den Button2 kann ich testweise nochmal den aktuellen Progress-Wert in einem Label anzeigen lassen)

class MyProcessClass
    {
        //private Object thisLock = new Object();
        private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
        
        private int var1 = 0;
        private int var2 = 0;
        private int progress = 0;



        public MyProcessClass()
        {

        }

        public void StartProcessThread()
        {
            Thread processThread;
            processThread = new Thread(ProcessMethod);
            processThread.Start();
        }

        public void LongMethod()
        {
            for (int i = 0; i <= 100; i++)
            {
                var1 = i;
                progress = i;
                for (int j = 0; j <= 1000; j++)
                {
                    for (int k = 0; k <= 10000; k++)
                    {
                    }
                }
            }
        }

        public void ProcessMethod()
        {
            int par1 = var1;
            int par2 = var2;


            for (int i = 0; i <= 100; i++)
            {
                progress = i;
                for (int j = 0; j <= 1000; j++)
                {
                    par1++;
                    for (int k = 0; k <= 10000; k++)
                    {
                        par2++;
                    }
                }
            }

            // Wait until the ReadLock is entered
            do
            {
                cacheLock.EnterReadLock();
            }
            while (!cacheLock.IsReadLockHeld);              // <<<=== HIER SOLL DIE LESESPERRE EINTRETEN
            LongMethod();
            var1 = par1;
            var2 = par2;
            // Exit ReadLock
            cacheLock.ExitReadLock();
        }

        public int[] GetProcessVars()
        {
            int[] vars = new int[2];
            vars[0] = var1;
            vars[1] = var2;
            return vars;
        }

        /// <summary>
        /// Progress in %.
        /// </summary>
        public int Progress
        {
            get { return progress; }
            set { progress = value; }
        }
    }

    public partial class Form1 : Form
    {
        private MyProcessClass myProcess = new MyProcessClass();
        

        

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            myProcess.StartProcessThread();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            progressBar1.Value = myProcess.Progress;             // <<<=== HIER WIRD ALLE 0,1 SEKUNDEN EIN ATTRIBUT AKTUALISIERT
        }

        private void button2_Click(object sender, EventArgs e)
        {
            label1.Text = myProcess.Progress.ToString();
            label1.Text = myProcess.GetProcessVars()[0].ToString();
        }
    }

Warum funktioniert die Lesesperre nicht?

Vielen Dank schonmal im Voraus.

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo dahaack,

An einem Progressbar der Windowsform (wird durch Timer aktualisert)

Warum so umständlich? Feure in der Thread-Methode wenn Fortschritt passiert ein Event und dessen Handler aktualisiert die Progressbar.

Für dein Vorhaben ist der ReaderWriterLock(Slim) gänzlich ungeeignet.

Zitat von: ReaderWriterLockSlim
Represents a lock that is used to manage access to a resource, allowing multiple threads for reading or exclusive access for writing.

Verwende also nur einen Monitor bzw. den Syntax-Zucker lock.

Du solltest generell die MSDN dazu lesen.

Zitat von: ReaderWriterLockSlim.IsReadLockHeld
This property is intended for use in asserts or for other debugging purposes. Do not use it to control the flow of program execution.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

D
dahaack Themenstarter:in
47 Beiträge seit 2011
vor 12 Jahren

Hallo Gü,

danke für deine Antwort.

Represents a lock that is used to manage access to a resource, allowing multiple threads for reading or exclusive access for writing.

Ich sehe da genau mein Problem: Ich habe zwei Threads, die sich bei der Variablenübergabe ein wenig abstimmen müssen.

Verwende also nur einen Monitor bzw. den Syntax-Zucker lock.

Okay, werd mir das mal anschauen, danke.

Du solltest generell die MSDN dazu lesen.

Das mache ich natürlich, wie gesagt, ich sehe in der Beschreibung genau mein Problem.

Hinweis von gfoidl vor 12 Jahren

...und auch [quote]-Tags statt [csharp]-Tags für Kommentare verwenden.

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo dahaack,

nochwas: bevor du Multi-Threading umsetzt lies dich überhaupt in diesem Thematik ein. Die ist nich ohne es können sehr viele Fehler passieren - v.a. zur Laufzeit. In deinem obigen Code wimmelt es nur so von potentiellen Tücken (nur als Stichwort: volatile)*. Schau dir besser mal Threading in C# von Joe Albahari an und danach Concurrency: What Every Dev Must Know About Multithreaded Apps und erst dann beginne erst danach mit dem Programmieren.

* obwohl das zwar für das konkrete Problem eine Lösung ist, aber nicht für das prinzipielle. Das habe ich oben schon erwähnt: statt Polling (und auch mit dem Timer ist das nix anderes) verwende ein Ereignis. Siehe [FAQ] Eigenen Event definieren / Information zu Events.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

D
dahaack Themenstarter:in
47 Beiträge seit 2011
vor 12 Jahren

Hallo Gü,

(nur als Stichwort: volatile)

Jo danke, wenn ich einmal mehr Threads benutze werd ich dran denken.

Das habe ich oben schon erwähnt: statt Polling (und auch mit dem Timer ist das nix anderes) verwende ein Ereignis.

Auch hier nochmal danke für deinen Tipp. Dieses Testprogramm ist so zusammengewachsen. Mit einem sauberen durchdachten Programm hat das nichts zu tun sondern ist ausschließlich zum Testen der Threads. 😉

Grüße

dahaack

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo dahaack,

du tust dir aber selbst keinen gefallen wenn du mit schlecht zusammengehackten Programmen lernen versuchst. Das falsche Wissen bekommst du dann nimmer so leicht raus.

wenn ich einmal mehr Threads benutze werd ich dran denken.

Daran musst du denken wenn die Threadzahl > 1 ist.

So, nachdem alles wichtige gesagt wurde und wir uns diesmal wohl richtig verstanden haben schließe ich das Thema als Prävention. Nicht dass noch mehr Hackerei kommt 😉

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Thema geschlossen