Laden...

Transfer von Arrays zwischen 2 Forms über Pointer

Erstellt von Aschratt vor 16 Jahren Letzter Beitrag vor 16 Jahren 2.094 Views
Aschratt Themenstarter:in
97 Beiträge seit 2007
vor 16 Jahren
Transfer von Arrays zwischen 2 Forms über Pointer

Hey!

Ich habe ein Problem. Ich versuche ein 3Dimensionales Array an eine Andere Form zu übergeben. Im Moment mache ich das so:

Form1:

            int[] NodesCount = new int[64];
            float[,,] CarNodesArray = new float[64, listView1.Items.Count, 3];

            //Zuweisung

            Image frm = new Image(CarNodesArray, NodesCount);
            frm.Show();

und Form2:

            DrawNodes = new float[64, Nodes.Length / 3, 3];
            DrawNodes = Nodes;
            Area = ItemsPerArea;

Ist ja alles kein Problem, außer, dass die Datenmengen, die in dem Array liegen verdammt groß sind, und es Irgendwann bei der Stelle

            DrawNodes = Nodes;

Zu einer OutOfMemoryException kommt.

Logisch, denn Da wird alles in den Stack gepusht und der ist dafür zu klein.

Also wurde mir gesagt ich soll es über Pointer versuchen. Gut. Ich habe zwar noch nie mit Pointern in C# gearbeitet, aber von C/C++ her weiß ich etwa was man sich darunter vorstellen kann. Also ran an die Arbeit. Ich bin jetzt da:

            unsafe
            {
                int* CarNodesPtr = &CarNodesArray;
                int* NodesCountPtr = &NodesCount;
            }

Jetzt sagt er mir aber was, dass es nicht möglich ist ein pointer auf ein array float[][][] zu deklarieren.

Kann mir einer weiter helfen?!

Danke!

K
174 Beiträge seit 2006
vor 16 Jahren

Hallo Aschratt,

mit Pointern zu arbeiten sollte hier nicht notwendig sein.
Außerdem ist ein Array ja in gewisser weise ein pointer... (zumindest konnte ich in C++ ein array immer genauso behandelt...) ob es in c# genauso ist weiß ich nicht, da ich noch nie in die situation kam pointer zu nutzen... und wir arbeiten auch mit großen Datenmengen...

Interessant wäre es vielleicht, wenn wir wüssten, was genau Nodes und DrawNodes eigentlich sind bzw. was im Setter von DrawNodes passiert...

P.S.: Wenn der Stack voll wäre, würde eine StackOverflowException kommen... OutOfMem weißt auf den Heap hin (und/oder auch auf den festplattenspeicher... bin mir da aber nicht sicher)

Grüße,
Kani

// EDIT:
Vielleicht kannst du uns ja auch mal den Stacktrace posten!

0
767 Beiträge seit 2005
vor 16 Jahren

arrays werden in c# "by reference" übergeben. dir geht der speicher irgendwo anders verloren, aber nicht weil du die arrays hin und her übergibst, weil dabei nur die referenz weitergegeben wird. eine kopie vom array wird dabei weder im stack noch im heap erzeugt.

loop:
btst #6,$bfe001
bne.s loop
rts

Aschratt Themenstarter:in
97 Beiträge seit 2007
vor 16 Jahren

Heap und Stack is doch im Endefekt egal... Fakt ist, dass irgendwelcher Speicher voll ist.

Nodes ist der Name des Arrays, wie die 2te Form ihn übergeben bekommt und DrawNodes der Name des Arrays, wie ihn die 2te Form in anderen Funktionen nutzt... (In dem Fall zum Zeichnen mit OpenGL... Im Array sind 3D-Punkte. Untergliedert in 64 Areale mit n Punkten zu je 3-Koordinaten.).

Das heißt Form2 bekommt CarNodesArray als "Nodes" übergeben.

Gibt es denn da noch eine andere Möglichkeit, damit der Speicher dann nicht voll wird?

0
767 Beiträge seit 2005
vor 16 Jahren

das übergeben des arrays macht den speicher nicht voll, weil dabei keine kopie erzeugt wird. also entweder erzeugst du selber kopien oder etwas anderes macht den speicher voll.

OutOfMemoryException ist mir auch schon in zwei Situationen aufgetreten, die mit "out of memory" rein gar nix zu tun hatten. Die eine kann ich leider nicht mehr nachstellen (hätte aber eher eine NullReference oder noch besser ArgumentNull sein sollen), die zweite war eine routine in der art:


protected void OnPaint(object sender, IrgendwelcheEventArgs e)
{
  Graphics g = e.Graphics;
  for (ziemlich lang)
  {
    g.DrawArc(recht klein und mit Winkel unter 0.01 Grad);
  }
}

dabei tritt die auch auf und zwar direkt an der g.DrawArc();

schau mal, wie groß dein Array überhaupt ist -> sizeof().

loop:
btst #6,$bfe001
bne.s loop
rts

Aschratt Themenstarter:in
97 Beiträge seit 2007
vor 16 Jahren

Es ist auch nicht die Übergabe die den Speicher voll macht. Das habe ich doch schon gesagt. Es ist das kopieren der Daten eines Arrays in den Anderen. Dabei hat man kurzzeitig 2 Ziemlich große Arrays, und das macht den Speicher voll.

Das Array ist atm ca. 21 Mb groß!

0
767 Beiträge seit 2005
vor 16 Jahren

ich vermute dass das array ziemlich oft kopiert wird, und du jedesmal eine neue kopie erzeugst. wenn das array seine größe behält, könntest du das "alte" array wieder verwenden und die aktuellen daten dort reinkopieren, anstatt ein neues array anzulegen.

vielleicht ist es auch gar nicht nötig, eine kopie vom array zu erstellen, dann würd sich das sowieso erübrigen.

loop:
btst #6,$bfe001
bne.s loop
rts

Aschratt Themenstarter:in
97 Beiträge seit 2007
vor 16 Jahren

der fehler kommt ja sobald die form erzeugt wird, nämlich genau dann, wenn ich das array, was Form2 aus Form1 übergeben bekommt dem Array zuweiße, welches Form2 global nutzen kann, denn das Array, was übergeben wird steht ja nur während der Initialisierung der Form zur Verfügung. Wenn es ne möglichkeit gibt das Übergebene Array für die ganze Laufzeit von Form2 für Form2 nutzbar zu machen dann her damit. Das würde mir reichen ^^

Ich habe halt gedacht per Pointer auf das Array könnte ich Speicherplatz sparen, aber es scheint ja nicht so einfach zu gehen.

1.549 Beiträge seit 2004
vor 16 Jahren

Singletone könnte dir weiter helfen aber eigentlich ist das schlechtes Designe

Wir Arbeiten eigendlich nicht wir nehmen nur das geld

40 Beiträge seit 2007
vor 16 Jahren

Wenn du den Array an Form2 übergibst und und dann in der Form ein Verweis darauf speicherst bleibt das Array erhalten und nicht kopiert.

In Form2 sollte das dann ungefähr so aussen:

private float[,,] _DrawNodes;

public Form2(float[,,] Nodes, int ItemsPerArea);
{
            DrawNodes = Nodes;
            Area = ItemsPerArea;
}

(Dein Konstruktor hab ich jetzt mal einfach mal geraten)

Wichtig ist dass die Anweisung

DrawNodes = new float[64, Nodes.Length / 3, 3];

den Speicher für das Objekt auch schon belegt - Wenn du nur eine Referenz (= Pointer) übergibst ist das unnötig und du brauchst nur den Typ zu deklarieren.

0
767 Beiträge seit 2005
vor 16 Jahren

Original von Aschratt
denn das Array, was übergeben wird steht ja nur während der Initialisierung der Form zur Verfügung.

wenn du das so übergibst wie von Rumpel vermutet, dann wird nichts kopiert und kein speicher belegt.

such mal nach "call by reference" bzw "call by value"

loop:
btst #6,$bfe001
bne.s loop
rts

Aschratt Themenstarter:in
97 Beiträge seit 2007
vor 16 Jahren

Krass es geht! Danke Rumpel!