Hallo,
ich würde gerne die Methode **transmit.fm(dataBuffer, datalenght); **
als Thread aufrufen, da das verarbeiten der Methode den restlichen Ablauf des Programms zu sehr verzögert. Daher würde ich es gerne vom rest abkoppeln.
using transmitter
namespace poster
{
public class IoPacket
{
public void PostReceive()
{
try
{
transmit.fm(dataBuffer, datalength);
}
.
.
.
Die Methode schaut so aus:
namespace poster
{
class transmit
{
public static void fm(byte[] buffer, int bytesRead)
{ ... }
.
.
.
diese benötigt ein Bytearray und die Länge des Bytearrays als Integer.
Wie kann ich denn nun die Methode als Thread aufrufen und das Bytearray, Integer mitübergeben?
Parameterized Thread Start akzeptiert ja nur einen Parameter. Wie dann aber jetzt mit zweien?
Könnte mir bitte jemand dabei helfen?
mfg
skato
Edit: Methode nicht Funktion
Hallo,
Parameterized Thread Start
das bedeutet auch selbst einen Thread erstellen was in den meisten Fällen schlechter ist als eine Thread aus dem ThreadPool zu verwenden.
byte[] dataBuffer= ...;
int datalenght= ...;
ThreadPool.QueueUserWorkItem(_ => transmit.fm(dataBuffer, datalenght));
Das funktionert aufgrund von Closures und so ist es auch der bevorzugte Weg eine Methode (nicht Funktion, da in C# alles Methoden sind) in einem (ThreadPool-) Thread auszuführen.
Ohne Closures siehe :rtfm: für QueueUserWorkItem.
Ab .net 4.0 bietet es sich an mit Tasks zu arbeiten, also
byte[] dataBuffer= ...;
int datalenght= ...;
Task.Factory.StartNew(() => transmit.fm(dataBuffer, datalenght));
BTW: Schau dir mal Namenskonventionen an.
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!"
Hallo Skato,
Es gibt noch 2 andere Möglichkeiten
1: Ruf die transmit.fm(dataBuffer,datalength) in einer separaten Methode auf, und nicht direkt als Parameter der Thread.Start Methode. Deklarier dataBuffer,datalength lokal, dann kannst du die foo Methode im neuen Thread starten sofern dataBuffer,datalength den Zugriff zulassen.
private void foo()
{
transmit.fm(dataBuffer, datalength);
}
Dann gibs 2 Möglichkeiten:
2: Erstell eine Hilfsmethode die du dann wie folg die foo(o) in der ParameterizedThreadStart aufrufst.
private void foo(object o)
{
object[] oo = (object[])o;
transmit.fm(oo[0], oo[1]); //auf das richtige Casten
}
Gruß
Michael
Danke!
ich hab das jetzt so realisiert:
ThreadPool.QueueUserWorkItem(_ => transmit.fm(dataBuffer, datalenght));
Ich verwende übrigens das Net 3.5
Ist denn Thread Start so schlecht?
mfg
skato
Geht auch super via Delegate.BeginInvoke. Einfach ein passendes Delegate erstellen, bzw. Action<> oder Func<> verwenden. Damit musst du nicht auf Typsicherheit verzichten und kannst auch wenn du brauchst einen Rückgabewert verwenden.
Schau dir bitte auch den Rückgabewert von BeginInvoke. Mit dem Waithandle hast du automatisch eine Thread.Join-Funktion.
Nachteil des ganzen, beim Aufruf von BeginInvoke solltest du später EndInvoke aufrufen. Besonders bei den MS Implementationen könnten sonst Speicherlecks entstehen.
Selber Threads zu erstellen, ist meist nur sinnvoll, wenn du die volle Kontrolle(Überwachung) über den Thread brauchst oder es sich um eine "lange" Aufgabe handelt. Wenn du nur etwas parallelisieren möchtest, ist die direkte Verwendung von Thread verkehrt, da allein das Erstellen des eines neuen Threads Ressourcen und Zeit verbraucht. Threadpool (BeginInvoke zählt auch dazu) verwenden existierende Threads, die nur drauf warten endlich mal was zu tun zu bekommen.
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
vielen Dank! das habe ich garnicht gewusst!
also sollte ich anstatt:
//Die TCP-Server (Listener) Threads für RM und FM starten
//R1 Server Thread
Thread R1_Server = new Thread(listener_R1.R1_main);
R1_Server.Start(); //Thread starten
Thread.Sleep(300);
//R2 Server Thread
Thread R2_Server = new Thread(listener_R2.R2_main);
R2_Server.Start(); //Thread starten
Thread.Sleep(300);
//RM Server Thread
Thread FM_Server = new Threading.Thread(listener_fm.fm_main);
FM_Server.Start(); //Thread starten
Thread.Sleep(300);
immer dies hier benutzen ?
ThreadPool.QueueUserWorkItem(_ => listener_R1.R1_main());
Die Methoden laufen ja eh in einer Dauerschleife und werden erst beendet wenn das Programm geschlossn wird. Es geht halt hauptsächlich um Paralellisierung.
mfg
skato
Hallo Skato,
in dem Fall laufen die Threads (relativ) lange und der Vorteil der geringeren Startzeit fällt nicht ins Gewicht. Dagegen entsteht der Nachteil, dass du ThreadPool-Threads, die vielleicht später für andere Aufgaben benötigt werden, eben relativ lange blockierst. Im konkreten Fall solltest du also bei normalen Threads bleiben.
herbivore