Avatar billede nemezis_aalborg Nybegynder
25. august 2006 - 15:15 Der er 5 kommentarer og
1 løsning

Tråde, C#, and queues

Hejsa,

har lidt problemer med en kø, som jeg håber i kan hjælpe med.

Jeg har en klasse med en kø, en funktion til at tilføje ting til køen og en tråd til at tømme køen.

Altså mange forskellige tråde tilføjer ting til køen, men kun en tømmer den.

Problemet er så at jeg gerne vil have den tråd, der tømmer køen til at sove når køen er tom (ik spinwait).

Her er lidt kode:
------------
public class QueueHandler
{
    private System.Collections.Generic.Queue<int> queue =
        new System.Collections.Generic.Queue<int>();

    private System.Collections.Generic.Queue<int> writeQueue =
        new System.Collections.Generic.Queue<int>();

    System.Threading.Thread thread = null;

    public QueueHandler()
    {
        // Create worker thread.
        this.thread = new System.Threading.Thread(this.WorkerThread);
        // Set priority high.
        this.thread.Priority = System.Threading.ThreadPriority.AboveNormal;
        // Start thread.
        this.thread.Start();
    }

    public void WorkerThread()
    {
        while (true)
        {
            // Switch queues.
            System.Threading.Monitor.Enter(this.queue);
            this.writeQueue = this.queue;
            this.queue = new System.Collections.Generic.Queue<int>();
            System.Threading.Monitor.Exit(this.queue);
            // Print notification number.
            foreach (int e in this.writeQueue)
            {
                System.Console.WriteLine("Info:" + e.ToString());
            }
            #warning Do something to awoid busywaiting (sleep)...
        }
    }

    public void AddToQueue(int info)
    {
        System.Threading.Monitor.Enter(this.queue);
        this.queue.Enqueue(info);
        System.Threading.Monitor.Exit(this.queue);
        #warning Wake thread to do work
    }
}
------------
Avatar billede arne_v Ekspert
25. august 2006 - 15:25 #1
plejer man ikke at lade Dequeue kalde Wait og saa lade Enqueue kalde PulseAll i
den slags situationer ?
Avatar billede nemezis_aalborg Nybegynder
25. august 2006 - 15:57 #2
Hmm... måske.. kan du komme med et eksempel på hvordan man gør?
Avatar billede nemezis_aalborg Nybegynder
25. august 2006 - 16:05 #3
Egentlig tænkte jeg på at lave en lock hvori jeg får workertråden til at sove, og når man så putter noget i køen laver man en interrupt på workertråden, men der kommer race condition :(
Avatar billede arne_v Ekspert
25. august 2006 - 16:21 #4
fra lageret:

using System;
using System.Collections;
using System.Threading;

namespace E
{
    public abstract class Command
    {
        public abstract void Execute();
    }
    public class Test1Command : Command
    {
        private int v;
        public Test1Command(int v)
        {
            this.v = v;
        }
        public override void Execute()
        {
            Console.WriteLine("Test1 thread = " + Thread.CurrentThread.Name + " v = " + v);
        }
    }
    public class Test2Command : Command
    {
        private int v;
        public Test2Command(int v)
        {
            this.v = v;
        }
        public override void Execute()
        {
            Console.WriteLine("Test2 thread = " + Thread.CurrentThread.Name + " v = " + v);
        }
    }
    public class CommandQueue
    {
        private Queue q;
        public CommandQueue()
        {
            q = new Queue();
        }
        public void Enqueue(Command cmd)
        {
            Monitor.Enter(q);
            q.Enqueue(cmd);
            Monitor.PulseAll(q);
            Monitor.Exit(q);
        }
        public Command Dequeue()
        {
            Command cmd = null;
            do
            {
                Monitor.Enter(q);
                if(q.Count > 0)
                {
                    cmd = (Command)q.Dequeue();
                }
                else
                {
                    Monitor.Wait(q);
                }
                Monitor.Exit(q);
            } while(cmd == null);
            return cmd;
        }
    }
    public class WorkerThread
    {
        private CommandQueue cq;
        public WorkerThread(CommandQueue cq)
        {
            this.cq = cq;
        }
        public void Run()
        {
            while(true)
            {
                Command cmd = cq.Dequeue();
                cmd.Execute();
            }
        }
    }
    public class WorkerThreadPool
    {
        private WorkerThread[] wt;
        public WorkerThreadPool(int n, CommandQueue cq)
        {
            wt = new WorkerThread[n];
            for(int i = 0; i < wt.Length; i++)
            {
                wt[i] = new WorkerThread(cq);
                Thread t = new Thread(new ThreadStart(wt[i].Run));
                t.Name = "Thread-" + (i + 1);
                t.Start();
            }
        }
    }
    public class TestClass
    {
        public static void Main(string[] args)
        {
            CommandQueue qc = new CommandQueue();
            WorkerThreadPool wtp = new WorkerThreadPool(3, qc);
            qc.Enqueue(new Test1Command(1));
            qc.Enqueue(new Test2Command(2));
            qc.Enqueue(new Test1Command(3));
            qc.Enqueue(new Test2Command(4));
            Thread.Sleep(5000);
            Environment.Exit(0);
        }
    }
}
Avatar billede arne_v Ekspert
30. september 2006 - 21:00 #5
OK ?
Avatar billede nemezis_aalborg Nybegynder
29. november 2006 - 12:24 #6
Jeps... super!
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester