Ich lausche in meinem Programm einer Art Börsentickerstream. In meinem Fenster starte ich in der button_click(..) die Funktion StartBitcoinchartsTicker(). Diese startet nun in einem neuen Thread die bitcoinchartlistener() funktion die nun in einer Endlosschleife den Stream abhört. Der Thread wird gespeichert als ThreadX
Wenn ich mein Programmfenster schließe und damit das Programm beenden will, dann "lebt" bitcoinchartslistener einfach weiter. Auch ein ThreadX.abort() bringt nichts. in der Receive funktion kommt dieser Befehl sich zu beenden wohl nicht zur ausführung.
Wie kann ich mein Programm vollständig beenden?
Ich habe folgenden Code:
static bool isBitcoinchartsTickerRunning = false;
public static System.Threading.Thread StartBitcoinchartsTicker()
{
if (isBitcoinchartsTickerRunning == false)
{
return run(() => { bitcoinchartlistener(); });
}
return null;
}
static BitCoinChartsData bitcoinchartlistener()
{
Socket sock = null;
IPHostEntry hostEntry = null;
hostEntry = Dns.GetHostEntry("bitcoincharts.com");
// Nutze die Eigenschaft AddressFamily von IPEndPoint um Konflikte zwischen
// IPv4 und IPv6zu vermeiden. Gehe dazu die Adressliste mit einer Schleife durch.
foreach (IPAddress address in hostEntry.AddressList)
{
IPEndPoint ipo = new IPEndPoint(address, 27007);
Socket tempSocket = new Socket(ipo.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp);
tempSocket.Connect(ipo);
if (tempSocket.Connected)
{
sock = tempSocket;
break;
}
else
{
continue;
}
}
Byte[] bytesReceived = new Byte[94096];
// Instanziere ein gültiges Socket Objekt mit den übergebenen Argumenten
if (sock == null)
{
if (OnError != null)
{OnError("Could not connect to Bitcoinchart-Datastream");}
}
isBitcoinchartsTickerRunning=true;
int bytes = 0;
// Empfange die Daten und konvertiere sie
do
{
bytes = sock.Receive(bytesReceived, bytesReceived.Length, SocketFlags.None);
// kovertiere die Byte Daten in einen string
//page = page + Encoding.ASCII.GetString(bytesReceived, 0, bytes);
if(OnNewBitcoinchartData!=null)
{
string JSON = Encoding.ASCII.GetString(bytesReceived, 0, bytes);
string[] JSONs = JSON.Split(new string[]{"\0"},StringSplitOptions.RemoveEmptyEntries);
foreach(string JS in JSONs)
{
JS.Replace("\0","");
OnNewBitcoinchartData(new BitCoinChartsData(JS));
}
}
} while (bytes > 0);
// Unterbinde alle weiteren Send() und Receive() Aktivitäten am Socket
sock.Shutdown(SocketShutdown.Both);
sock.Close();
if (OnError != null)
{ OnError("Could not connect to Bitcoinchart-Datastream"); }
isBitcoinchartsTickerRunning = false;
return null;
}
Ich habe mehrere Kartendecks gleichzeitig, nicht eines an dem Parallel herrum gedoktert wird...ich bin kein bloedie ;)
Das Seedarry entleert sich wenn parallel aus einer Randominstanz Zufallszahlen erzeugt werden. Ich denke es pasiert Folgendermassen:
Thread ruft auf Core 1 rnd.Next() auf. Mitten in der Erzeugung wechselt der Thread von Core 1 auf Core 2 dabei *mysterioese hexenmagie * teil des Seedarrys ist verloren. Wenn das oft genug passiert, ist das Seedarry irgendwann nur noch mit Nullen gefuellt, ergo werden nur noch Nullen zurueck gegeben. Wenn ich viele Randominstanzen habe, verkleiner sich die Gefahr, da diese auch nur eine Begrenzte Lebensdauer haben und nicht so lange leben wie ein Thread!
Das ist alles recht schmutzig, fuer ein Privatprojekt aber ausreichend ;D
Pro Thread konsistent sollte soviel bedeuten, wie alles was im Threat passiert ist save. Besser waere vielleich In thread konsisten...naja nicht wichtig.
Das äußert sich, indem irgendwann nur noch Nullen zurück gegeben werden. Das Seedarray entleert sich. Man kann nicht einfach hoffen das alles Pro Tread konsistent ist! Denn auch dann gibt es noch Seiteneffekte! Dies ist sogar auf einem Singlecore möglich wenn aus mehreren Threads auf eine Variable zugegriffen wird. Manchmal kommen die Daten dann eben aus dem Cach und manchmal aus dem Ram! Dadurch gehen Updates verloren! ähnliches scheint bei 2 Cores und einem Thread zu passieren. Oder ist dies Unmöglich? ich glaube leider nicht.
Ich benutze die Zufallsgeneratoren um einen Spielkartenstapel für ein Pokerspiel zu simmulieren.
Das ist wohl die Kritiche Stelle:
int CallWin = (from a in ParallelEnumerable.Range(0, Params.SerchStructure[Params.Level]) select WinningOfMove(eMove.Call, GameState.Clone(), this.Clone(), Stats.Clone(), BetterHands.Clone())).Sum();
In WinningOfMove Brauche ich dann jeweils die Zufalszahlen. Sonst ist nichts Nebenläufig
Wie man sieht, nichts Weltbewegendes, alles hat seine eigenen Instanzen.
herbivore, deine Lösung funktionier zumindest bei meinen Tests nicht!
Ich vermute es kommt durch den Prozessorcach zu Unstimmigkeiten, da der Thread unsinniger Weise von Core zu Core springt und alles ein wenig inkonsitent sein kann.
Es braucht also vorsichtshalber trozdem jeweils eigenständige Instanzen um ganz auf Nummer sicher zu gehen. Und wahrscheinlich ist das auf sehr Lange sicht noch immer nicht ganz Sicher...
Ich wünsche mir die 90er mit immer schneller werdenden Singlecores zurück ;D
[ThreadStatic]
static private Random rnd;
static Random MasterRnd = new Random();
public static Random GetGoodRandomMT()
{
if (rnd == null)
{
Console.WriteLine("HAHAHHAHAHAAAA!");
lock (MasterRnd)
{
rnd = new Random(MasterRnd.Next());
}
}
return new Random(rnd.Next());
}
Ich habe einen Code in dem ich viele Zufallsgeneratoren brauche. Und damits schneller läúft ist alles mit Linq Parallelisiert.
Eine Instanz von Random ist ja nun nicht threadsave. Und zu allen übel, wenn man viele Instanzen in kurzer Zeit erstellt, sind sie alle gleich. Meine Lösung für das Problem sieht so aus:
static private Random rnd = new Random();
static Dictionary<int, Random> PrivatRNDGenerators = new Dictionary<int, Random>();
public static Random GetGoodRandomMT()
{
int ID = System.Threading.Thread.CurrentThread.ManagedThreadId;
if(PrivatRNDGenerators.ContainsKey(ID))
{
return PrivatRNDGenerators[ID];
}
lock (rnd)
{
Console.WriteLine("AHA!");
PrivatRNDGenerators.Add(ID,new Random(rnd.Next()));
return PrivatRNDGenerators[ID];
}
throw new Exception("KA!");
//return new Random(rnd.Next());
//}
}
Aber obwohl ich schön säuberlich nach threads trenne, gibt es Fehler, das heisst, die Instanzen in dem Dictionery geben nur noch Nullen statt Zufallszahlen zurück.
Woran kann das liegen?
Eine Funktionierende Lösung war:
static private Random rnd = new Random();
public static Random GetGoodRandomMT()
{
lock (rnd)
{
return new Random(rnd.Next());
}
}
Aber das ist zu langsam, da warten sich die Threads tot...
Wie der Titel schon sagt, warum gibt GetHashCode eines Integerarrays immer etwas anderes zurück, obwohl alle Elemente zweier Arrays gleich sind?
Das hat sicherlich einen Logischen Grund, den ich gerne Verstehen würde!
Bei Strings funktioniert es doch auch! Und das sind ja quasi auch nur CharArrays?
Muss man solchen Lowlevelsachen bei den Standarddatentypen also immer erst Implementieren, wenn man irgend eine Datenstrucktur in einer Hashtable als Key nutzen will?
Keine Ahnung. Das sind Midi-Befehle, die die Töne erzeugen. Du kannst sicherlich irgendwo in den Einstellungen deines PCs regeln, wie Midis wiedergegeben werden.
Ich habe wohl wirklich irgend etwas nicht aktualisiert, bzw etwas war asynchron. Ich hab jedenfalls alles neu gemach und nun gings....die arbeit wars wert^^
Ist doch easy, irgend einen Punkt nehmen, und für jeden anderen Punkt den abstand berechnen. Alle Punkte die Nah genug sind kommen in die Liste Gruppe 1 plus Startpunkt. Nun vergleicht man noch jeden punkt in Gruppe eins mit den anderen, und findet so vielleicht neue Gruppe 1 Punkte.
Wenn nicht macht man Gruppe zwei auf und wählt neuen Zufälligen Punkt aus den verbleibenden. oder alle Punkte sind weg. Dann ist man fertig.
Wenn es nicht um Millionen Punkte geht, dürfte das auch schnell genug sein.
Man kann nicht einfach so eine KI programmieren. Du musst uns schon sagen, welche Aufgaben dein Programm lösen soll! Denn je nach Problem, gibt es unterschiedliche Ansätze!
verwendetes Datenbanksystem: ganz normales Array^^
Hallo!
Manchmal sagt Code mehr als tausend Worte ;D
int[,] test = new int[,] { { 2, 3, 4 }, { 5, 6, 7 } };
var list = from num in test select num;
Und der passende Fehler:
Error 4 'int[*,*]' does not contain a definition for 'Select' and the best extension method overload 'System.Linq.Enumerable.Select<TSource,TResult>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,TResult>)' has some invalid arguments
Error 5 Instance argument: cannot convert from 'int[*,*]' to 'System.Collections.Generic.IEnumerable<int>'
Ich will also mit Hilfe von Linq ein Mehrdim Array in ein eindimensionales Umwandeln. Warum geht das nicht? Wo is mein Denkfehler? Ich dachte man kann mit jedem Typ arbeiten, der IEnum... besitzt?
Ja, ich habe auch erwähnt, das man Heuristiken einbauen kann, die das Ganze sehr beschleunigen. Desweiteren steigt die Suchgröße Exponentiel, das ist wahr, aber auch die Rechenkraft steigt Exponentiell!
Früher war zb 4 Gewinnt ein Problem, heute kann man es in ein Paar Stunen durchrechnen.
Die Anzahl, der Probleme die man bis zum Schluss durchrechnen Kann, steigt jeden Tag. Und in 30 Jahren, glaube ich, das schon bedeutende Probleme innerhalb dieses Bereichs sind.
Die Zauberworte sind also Heuristik und Zeit.
Vorstellbar ist auch, das man das Programm zb eine Stunde rechnen lässt, und dann gibt es den Besten Zug aus. Den es bis dahin gefunden hat. Auch zwingt einen Niemand, eine Zielfunktion zu nutzen die nur das Matt bewertet. Man kann auch andere Sachen, wie Figurenwerte benutzen. Dadurch würden differenziertre bewertungen entstehen.
Und wie ich geschrieben habe, soll dieser Problemsolver unbekannte Objekte untersuchen können. Das empfinde ich als lernen und Forschen!
Ja, mir fehlen Grundlagen, aber ich sehe das als Vorteil. Diese Grundlagen kann ich jederzeit noch lernen. Aber jetzt will ich erstmal meine Eigenen Fehler machen ;D
Entschuldigt alle bitte! Ich sehe manchmal sehr schnell rot. Soziale Intelligenz fehlt mir vielleicht wirklich etwas. Ich mag es nicht wenn sich jemand rein hängt, der gar keine Ahnung hat. Manchmal ist schweigen doch Gold! In jeder Hinsicht!