Entwickler-Ecke
C# - Die Sprache - Thread Verwaltungproblematik
Darter - Do 01.09.11 02:28
Titel: Thread Verwaltungproblematik
Hey
Ich habe zu dem Thema ausführlich Google befragt, und auch einiges hilfreiches gefunen, wo unteranderem geraten wird, dass man sich eine Worker Klasse erstellen soll, was ich dann auch direkt gemacht hab.
Unteranderem erstelle ich ja eine WinForm, welche ja den Main Thread voll ausnutzt, und unteranderen wollte ich mit mehreren Threads eben verhindern, dass bei längeren Berechnungen, usw. die Form weiter beherrschbar bleibt.
Wie gesagt habe ich mir eine Worker Klasse erstellt, was ansich ja auch funktioniert, jedoch benötige ich nicht nur einen weiteren Thread, sondern mehrere.
Nun war meine Überlegung, ob ich an den Konstiktor der Worker Klasse einfach einen Funktionspointer übergebe, welche ich dann in der Worker-Methode Run ind Schleife immer wieder aufrufe, sodass ich mir nicht mehrere Worker Klassen erstellen muss, sondern jeweils immer nur eine Funktion, wo ich dann die Arbeit vollziehen lassen kann.
Hier mal meine Worker Klasse, vielleicht kann mir ja jemand bei der weiteren Vorgehensweise behilflich sein :-)
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46:
| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading;
namespace ThreadTest { class WorkerThread { private Thread thread; private bool isRunning;
public WorkerThread(int pFunc) { isRunning = true; }
public void StartThread() { if (thread == null || (thread != null && !thread.IsAlive)) { thread = new Thread(new ThreadStart(Run)); thread.Start(); } }
public void StopThread() { isRunning = false; }
public Thread GetThread() { return thread; }
private void Run() { while (isRunning) { Thread.Sleep(20); } } } } |
EDIT:
Zum besseren Verständniss noch etwas Pseydo Code :
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64:
| using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms;
namespace ThreadTest { class TestClass { public TestClass() { WorkerThread WThread = new WorkerThread(Pointer auf TestClassRun); }
public void TestClassRun() { } }
class WorkerThread { private Thread thread; private bool isRunning; private int *pFunc;
public WorkerThread(Pointer_auf_eine_Funktion) { pFunc = Pointer_auf_eine_Funktion; isRunning = true; }
public void StartThread() { if (thread == null || (thread != null && !thread.IsAlive)) { thread = new Thread(new ThreadStart(Run)); thread.Start(); } }
public void StopThread() { isRunning = false; }
public Thread GetThread() { return thread; }
private void Run() { while (isRunning) { pFunc(); Thread.Sleep(20); } } } } |
Th69 - Do 01.09.11 09:59
Hallo und :welcome:
mit Zeigern (Pointern) sollte man in C# nicht arbeiten (auch wenn es (teilweise) im unsafe-Modus funktioniert).
Das was du suchst, nennt sich "Delegate", s.a.mein Beitrag
http://www.c-sharp-forum.de/viewtopic.php?p=647271#647271
Der Konstruktor der Thread-Klasse erwartet auch ein Delegate (namens ThreadStart), welcher dann intern die übergebene Methode aufruft.
Darter - Do 01.09.11 17:54
Hey.
Ich hab mir das nun angeschaut und versucht, aber ich schätze ich mache irgend etwas falsch ?!?
Hier meine Worker Thread Klasse :
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50:
| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading;
namespace Test { class WorkerThread { private Thread thread; private bool isRunning; private MyDelegate func;
private delegate void MyDelegate();
public WorkerThread(MyDelegate del) { func = del; isRunning = true; }
public void StartThread() { if (thread == null || (thread != null && !thread.IsAlive)) { thread = new Thread(new ThreadStart(Run)); thread.Start(); } }
public void StopThread() { isRunning = false; }
public Thread GetThread() { return thread; }
private void Run() { while (isRunning) { func(); } } } } |
Hier die Klasse, vonder ich die WokrerThread klasse ansteuern will:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading;
namespace Test { class Thread1 { WorkerThread wThread = new WorkerThread(Run);
public WorkerThread GetWThread() { return wThread; }
public static void Run() { System.Console.Write("funktioniert\n"); Thread.Sleep(500); } } } |
Und zu guterletztr noch die Klasse, wo alles seinen ANfang findet xD
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52:
| using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading;
namespace Test { public partial class Form1 : Form { private Thread1 thread = new Thread1();
public Form1() { InitializeComponent(); }
private void MIFileClose_Click(object sender, EventArgs e) { thread.GetWThread().StopThread(); this.Close(); }
private void BStart_Click(object sender, EventArgs e) { this.BStart.Enabled = false; this.BStop.Enabled = true; thread.GetWThread().StartThread(); }
private void BStop_Click(object sender, EventArgs e) { thread.GetWThread().StopThread(); this.BStart.Enabled = true; this.BStop.Enabled = false; }
private void Form1_FormClosing(object sender, FormClosingEventArgs e) { thread.GetWThread().StopThread(); } } } |
EDIT: hab die Fehlermeldungen vergessen ^^
Quelltext
1:
| Fehler 1 Inkonsistenter Zugriff: Feldtyp "Test.WorkerThread.MyDelegate" ist weniger zugreifbar als Feld "Test.WorkerThread.func" C:\Users\....\documents\visual studio 2010\Projects\Test\Test\WorkerThread.cs 15 28 AoG |
Quelltext
1:
| Fehler 2 Inkonsistenter Zugriff: Parametertyp "Test.WorkerThread.MyDelegate" ist weniger zugreifbar als Methode "Test.WorkerThread.WorkerThread(Test.WorkerThread.MyDelegate)" C:\Users\...\documents\visual studio 2010\Projects\Test\Test\WorkerThread.cs 19 16 AoG |
Ralf Jansen - Do 01.09.11 18:19
C#-Quelltext
1: 2: 3:
| private MyDelegate func;
public WorkerThread(MyDelegate del) |
Der Konstruktor ist wohl eher selten benutzbar. Zumindest wird dein Testcode deine Run Methode nicht als MyDelegate darstellen können wenn MyDelegate private ist. Um den Konstruktor auch public nutzen zu können müssen alle Typen die in der Signatur verwendet werden auch public sein.
Darter - Do 01.09.11 18:50
Hey.
Ok, klare Sache :-) Habs angepasst und funktioniert auch, aber ist das denn eine "saubere" Methode sowas zu machen ?
Kha - Do 01.09.11 20:24
Darter hat folgendes geschrieben : |
aber ist das denn eine "saubere" Methode sowas zu machen ? |
Bis jetzt sehe ich noch nichts, was überhaupt für deine WorkerThread-Klasse anstatt eines einfachen Threads oder Tasks spricht. Gerade durch die TPL geht der Trend imo weg von monolithischen Klassen, die sich um die komplette Parallelisierung kümmern hin zum Hintereinanderschalten einfacher Primitive.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!