Laden...

Profil von tonka

myCSharp.de - Member Mitglied seit

Alle Beiträge

Hy@all,

ich suche nun seite geraumer Zeit mit Google vergebens nach einer Möglichkeit, wie ich beim Resize eines WPF-Window nur den Rahmen zeichnen lassen kann. Gibt es hier mit WPF schon Lösungen? Mir würde auch schon ein Stichwort reichen (denke das ich die ganze Zeit nach dem falschen Namen suche).

MfG
Tonka

02.08.2011 - 17:41 Uhr

Hey talla,

Das der GridSplitter nur fixe Höhen/Breiten einstellt habe ich mir schon gedacht.

Alternativ würd ich einfach in der unteren Zeile nen Expander nehmen den man auf und zuklappen kann statt die CheckBox. Wenn dann die Zeilenhöhe auf Auto ist, vergrößert und verkleinert die Höhe sich dann automatisch.

Der Vorschlag ist gut, jedoch kann ich es aus bestimmten Gründen hier leider nicht so machen.

Werd mich einmal damit beschäftigen ob es möglich ist den GridSplitter abzuleiten und eine Art reset einzubauen.

MfG
Tonka

01.08.2011 - 14:49 Uhr

Hy@all,

ich habe momentan ein Problem mit dem GridSplitter.

Ich habe ein Grid mit 3 Rows. In der ersten Ziele ist ein TreeView der immer eingeblendet ist. In der zweiten Zeile ist ein GridSplitter - der per default nicht sichtbar (collapsed) ist. In der dritten Zeile ist wieder ein Grid - Das ebenfalls per default ausgeblendet ist.

Nun zum Problem:
Wenn der User eine Checkbox aktiviert, werden Zeile 2 und 3 eingeblendet (mittels Binding). Der GridSplitter funktioniert und man kann die beiden UI-Element (Zeile 1 und 3) hin un her bewegen. Jedoch wenn man die Checkbox wieder deaktiviert und somit die Zeile 2 und 3 wieder Collapsed werden bleibt die Gridmanipulation leider aufrecht (siehe Bild). Ich habe jetzt schon vieles probiert, jedoch gelingt es mir nicht einen Reset der GridSpillters beim Ausblenden aufzurufen.

Kennt jemand von euch eine Lösung für dieses Problem???

MfG
Tonka

08.04.2011 - 11:32 Uhr

Hallo,

ich erstelle gerade mit VS2010 ein Setup. Es funktioniert alles prima, jedoch eine Sache bringe ich einfach (auch mit hilfe von google) nicht zusammen. Ich würde gerne meine Setup-Version automatisch in den Productnamen und in den Dateinamen setzten. War von VS bisher bei den meisten Dingen gewohnt, das man dafür ein Makro hat aller "[PRODUCTVERSION]".

Weiß jemand von euch, wie ich das mit VS-Mitteln bewerkstellingen kann?

MfG
Tonka

Hallo,

ich möchte einige Daten mit einem C#-Programm (WCF-Service) verschlüsselt in eine Datei schreiben. Am besten wäre eine XML-Datei. Soweit so gut, das hätte ich noch selbst zusammengebracht xD. Diese Datei müsste ich mit vc++, also unmanged ebenfalss wieder einlesen können.

Gibt es hier "Standardmittel" oder etwaiges?? Kenne mich leider in der Verschlüsselung nicht wirklich gut aus.

MfG
Tonka

Problem gelöst 😄

Man kann es so schreiben wie ich es von Anfang-an gemacht habe, jedoch muss die Klasse die man Draged als Serialisierbar markiert sein.

Danke für die Hilfe.

MfG
Tonka

dahingehend verstehe, dass du das dragging nur startest, wenn beide maustasten gehalten werden?

Das ist richtig. Die linke Maustaste brauch ich schon für was anderes. Wollte ursprünglich nur die rechte Maustaste dafür benutzten, jedoch funktioniert das scheinbar in WPF nicht!

Du müsstest also die Werte deiner Matrix mw in ein (2dim?)Array schreiben, das Array verschicken, und bei Empfang daraus eine neue Matrix instanzieren.

Die Matrix ist keine einfache Wertematrix, diese beinhaltet viele andere Matrizen und Referenzinformation => somit werd ich es mal mit einer Serialisierung versuchen.

MfG

und mir fällt auf, dass du mal "Matrix2D" benennst, mal "LightMatrix2D".

Mein Fehler, Matrix2D ist die Basisklasse - habs korrigiert, ändert aber nichts!

wie startest du denn das dragging?


        private Point RightMouseButtonDownLastPosition;

        private void UserControl_MouseMove(object sender, MouseEventArgs e)
        {
            if (!IsActive)
            {
                return;
            }
            if (e.LeftButton != MouseButtonState.Pressed || e.RightButton != MouseButtonState.Pressed )
            {
                return;
            }
            Vector diff = RightMouseButtonDownLastPosition - e.GetPosition(null);
            if (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance &&
                Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)
            {
                DataObject dragData = new DataObject(typeof(Matrix2D), Matrix);
                DragDrop.DoDragDrop(this, dragData, DragDropEffects.Move);
            }

            
        }

        private void UserControl_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            RightMouseButtonDownLastPosition = e.GetPosition(null);
        }

MfG

Das habe ich mir auch schon gedacht. Das werde ich in den nächste Tagen einmal in einer Testapplikation testen.

Naja, bin mir nicht sicher ob mir das weiterhilft. Vielleicht muss ich das Object COM-fähig machen, damit ich das tun kann!?

Visualizer kannst du dir wie Extensions für den Debugger vorstellen. Ein gutes Beispiel wäre Mole

Aso. Ich benutzte keinen Visualizer (aber das klingt interessant 😄 ).

Du sagtest "Drag N Drop" - geht es zufällig um hier dieses Problem Drag N Drop Exception?

Jein. Aus meiner Sicht sind das zwei seperate Problem, somit hab ich diese in 2 Threads aufgeteilt => oder irre ich mich da?

Hallo,

Visualizer? Es ist ein WPF Projekt.

Hy@all,

ich habe ein interessantes Problem mit Drag N Drop. Ich habe in meinem Programm Drag N Drop realisiert. Man kann in zwei (oder beliebig viele) Fenster (gleiche Klasse) Dateien laden (das Programm ist eine Art Viewer) und dann das eine Fenster auf das andere droppen. Wenn die Fenster-Instanzen innerhalb einer Programm-Instanzen laufen scheint es zu funktionieren. Start ich jedoch zweimal die exe und Droppe das eine Fenster auf das andere, so bekomme ich folgende Exception> Fehlermeldung:

COMException wurde nicht von Benutzercode behandelt
Ungültige tymed (Ausnahme von HRESULT: 0x80040069 (DV_E_TYMED))

Und hier ist meine Implimentierung:


private void LDV_DragOver(object sender, DragEventArgs e)
        {
            if (!e.Data.GetDataPresent(typeof(Matrix2D)))
            {
                e.Effects = DragDropEffects.None;
                //e.Handled = true;
            }

        }

private void LDV_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(LightMatrix2D)))
            {
                Matrix2D DroppedMatrix = e.Data.GetData(typeof(Matrix2D)) as Matrix2D; // hier kommt die Exception
                if (DroppedMatrix == null)
                {
                    MessageBox.Show("Could not recive dropped matrix");
                    return;
                }
                if (DroppedMatrix == this.LDV.Matrix)
                {
                    return;
                }
                _DroppedMatrix = DroppedMatrix;
                CMOperations.IsOpen = true;
            }
        }

Weiß jemand warum das passiert?

MfG
Tonka

Hy@all,

ich habe seit kurzem ein "witziges" Problem. Mein Studio hängt sich beim aktivwerden eines Breakpoint auf. Dies tritt bei mir aber eigentlich nur in Verbindung mit einem Drag N Drop Ereignis auf.

Ich habe zwei Fenster (selbe Klasse). Von dem einen Fenster wird auf das eine Fenster was gedropt und ab diesem Zeitpunkt hängt VS einfach beim debuggen. Mach ich das ganze ohne Debug, so bekomme ich kein Problem.

Hatte jemand auch schon einmal soetwas???

IDE: Visual Stuio 2010 Premium
OS: WinXP x64 SP2

MfG
Tonka

Konnte das Problem selbst lösen.

Statt dem DragEnter-Event muss das DragOver-Event benutzt werden. Außerdem muss man e.Handled auf true setzten.


private void Window_DragOver(object sender, DragEventArgs e)
        {
            if (!e.Data.GetDataPresent("FileName") || sender == e.Source)
            {
                e.Effects = DragDropEffects.None;
                e.Handled = true;//WICHTIG!
            }
        }

        private void Window_Drop(object sender, DragEventArgs e)
        {
            try
            {
                if (e.Data.GetDataPresent("FileName"))
                {
                    string[] filenames = e.Data.GetData("FileName") as string[];
                    if (filenames != null && filenames.Length > 0)
                    {
                        this.OFD.FileName = filenames[0];
                        Load(this.OFD.FileName);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error while drop: " + ex.Message, "Error");
            }
        }

MfG
Tonka

Hy@all,

ich habe ein Problem mit Drag N Drop. Ich habe ein ganz simples Window, wo ich einen Dateipfad aus z.B. dem Explorer "hinein-drope" - das funktioniert auch prima, jedoch möchte ich, dass bei unerwünschte Drops (z.B. es wird ein Bild gedropt, Datei-Extension passt nicht) kein Drop-Cursor-Symbol angezeigt wird. Eigentlich dachte ich, dass das mit ...


 e.Effects = DragDropEffects.None;

das eigentlich erledigt sein sollte, jedoch funktioniert das nicht wirklich.

Hier ist mein Code für die Drag N Drop Aktionen:


        #region Drag N Drop

        private void Window_DragEnter(object sender, DragEventArgs e)
        {
            if (!e.Data.GetDataPresent("FileName") || sender == e.Source)
            {
                e.Effects = DragDropEffects.None; // dieser Abschnitt wird in der runtime erreicht, jedoch zeigt das cursor-symbol an das gedropt werden kann, aber wieso??
            }
        }

        private void Window_Drop(object sender, DragEventArgs e)
        {
            try
            {
                if (e.Data.GetDataPresent("FileName"))
                {
                    string[] filenames = e.Data.GetData("FileName") as string[];
                    if (filenames != null && filenames.Length > 0)
                    {
                        this.OFD.FileName = filenames[0];
                        Load(this.OFD.FileName);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error while drop: " + ex.Message, "Error");
            }
        }

        #endregion

Mach ich hier irgendetwas falsch, ist e.Effects für etwas anderes gedacht?

MfG
Tonka

10.02.2011 - 22:18 Uhr

Hey,

1.) laut dieser Seite benutzten das schon einige Spam-Filter!

2.) Sollte der Absender nicht existieren (kann ja irgendwas bei SMTP sein), könntest du unter Umständen ebenfalls Bounce-Mails bekommen. Also solltest du auch schauen, wie du deine Mails makieren kannst, sofern das möglich ist.

Solltest du ein Plugin haben, würd mich das auch interessieren!

MfG
Tonka

Servus,

ich würd sagen das du WSS (Windows SharePoint Services) benutzten kannst.

MfG
Tonka

Oooooh man, bin ich blind gggggg

Was lernt man daraus, man sollte NIE zu spät noch programmieren 😉

Probier das morgen bei großen Tracer aus!

So hast du das also gemeint. Ich habe kurz deinen Code in mein Schema übersetzt, jetzt bekomme ich aber ein NullReferenceException

NullReferenceException not set to an instance of an object
Object reference not set to an instance of an object.

Ich gehe mal davon aus dass das die Meldung daher kommt, das der GC das object terminiert hat, oder?


//Tracer.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace ParallelObjectTest
{
    public class Tracer
    {
        [ThreadStatic()]
        private static WeakReference _WeakRefScene = null;

        public readonly Scene3D scene = null;

        public Tracer(Scene3D Scene)
        {
            this.scene = Scene;
        }

        public Scene3D CloneScene(Scene3D SceneToClone)
        {
            // hier muss noch Clone implimentiert werden
            return null;
        }

        public void Start()
        {
            List<object> objects = new List<object>();
            object lockobj = new object();

            double sum = 0.0;

            Parallel.For<double>(0, 10000, () =>
                {
                    Scene3D s = null;
                    if (_WeakRefScene == null)
                    {
                        s = CloneScene(this.scene);
                        objects.Add(s);
                        _WeakRefScene = new WeakReference(s);                        
                        Console.WriteLine("neues scene-objekt für thread: " + Thread.CurrentThread.ManagedThreadId.ToString());
                    }
                    else
                    {
                        Console.WriteLine("bestehendes objekt fuer thread: " + Thread.CurrentThread.ManagedThreadId.ToString());
                        s = (Scene3D)_WeakRefScene.Target;
                    }
                    s.Intersect();// hier passiert die NullException
                    
                    return 0.0;
                },
                (k, state, localstate) =>
                {
                    Console.WriteLine("k= " + k);
                    Thread.Sleep(1);
                    return 0.5;
                },
                (localstate) =>
                {
                    lock (lockobj)
                    {
                        sum += localstate;
                    }
                });

            objects.Clear();

        }
    }
}


//Scene3D.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ParallelObjectTest
{
    public class Scene3D
    {
        public bool Intersect()
        {
            // Funktion für Verschneidung für der Dreiecke
            return true;
        }
    }
}


//Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ParallelObjectTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Scene3D scene = new Scene3D();
            Tracer tracer = new Tracer(scene);
            tracer.Start();
            Console.WriteLine("press key for EXIT");
            Console.ReadLine();
        }
    }
}


Für mich kommt nur diese Variante in Frage, da das Scene3D Object dauernd arbeitet, somit bringt mir das zurücklegen nichts.

Hallo winSharp93,

Danke für deine Antwort.

Sicher, dass du das Objekt nicht auch zerstören willst, nachdem alle Aufgaben abgearbeitet sind?

Das ist fürm mich eigentlich ein das selbe - ich geh mal davon aus das du meinst wann es von GC zerstört wird, oder?

Dann bleibt dir vielleicht noch die Kombination aus mit ThreadStaticAttribute markierten WeakReferencen und einer statsischen Liste:
Prüfe jedes Mal (evtl. auch in dem Initialisierungscallback; dann ist ja egal, wie oft es aufgerufen wird), ob das entsprechende Feld null ist. Wenn ja, erstellst du es und speicherst es in der Liste.
Am Ende musst du dann nur alle Elemente in der Liste disposen bzw. die Liste nullen, damit die Objekte tatsächlich eingesammelt werden können.
Ohne die Verwendung einer Liste kann es vorkommen, dass die Objekte evtl. schon vom GC eingesammelt werden, obwohl der entsprechende Thread nochmal aktiv werden könnte - die WeakReferencen verhindern hingegen, dass ein Thread die Objekte länger als nötig am Leben erhält (wenn er z.B. wieder in den ThreadPool zurück kehrt).

Das klingt sehr gut, wusste nicht das es soetwas gibt. Jedoch habe ich hier Code-technisch einige Probleme das umzusetzt, da mir nicht ganz klar ist wo genau ich im Code das platzieren soll.

Hier ist mein momentaner TestCode (vielleicht könntest du in korrigieren):


//LocalState.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ParallelDataAccessTest.Data
{
    public class LocalState
    {
        [ThreadStatic()]// <= meinst du das hier
        public readonly Scene3D scene = null;

        public LocalState(Scene3D s)
        {
            scene = s;
        }
    }
}


    public class Tracer
    {
        public Scene3D scene = null; // dieses Object wird von ausen zugewiesen und muss pro Thread geklont werden
        public List<Scene3D> scenes = null; // meintest du das mit der Liste???

        public LocalState InitThreadLocalState()
        {
            Console.WriteLine("Init threadlocalstate ThreadID= " + Thread.CurrentThread.ManagedThreadId.ToString());

// hier ist mir leider nicht ganz klar, wie ich das von dir beschrieben Verhalten implimentieren soll!!!
           
            LocalState loci = new LocalState();
            return loci;
        }

        public void Start()
        {
            Stopwatch watch = new Stopwatch();
            Int32 size = 1000;
            LocalState Sum = new LocalState();           

            scenes = new List<Scene3D>();

            watch.Restart();
            Object localobj = new object();
            Parallel.For<LocalState>(0, size, () => InitThreadLocalState(), (k, loop, localstate) =>
            {
                localstate += Trace();
                Console.WriteLine("ThreadID= " + Thread.CurrentThread.ManagedThreadId.ToString() + " k= " +k.ToString());
                return localstate;

            },
            (localstate) =>
            {
                lock (localobj) { Sum += localstate; } }
                    );
            watch.Stop();

            Console.WriteLine("zw= " + Sum.ToString());
            Console.WriteLine("time= " + watch.Elapsed.ToString());
        }

Was soll ich genau ion der Liste speichern, die LocalStates, oder meine Klon-Objekte? Soetwas ähnliches habe ich schon probiert und habe dann eine OutOfMemoery-Exception bekommen.

Was bringt mir eigentlich die WeakReferencen, denn was macht es für einen Sinn, das der GC das Objekt terminieren kann obwohl es noch in Verwendung ist???

Alternativ kannst du vielleicht auch eine Art Pool implementieren?

Das habe ich mir auch schon gedacht, würde aber lieber Parallel.For benutzten, da hier angeblich die Performance besser ist!

MfG

Mittlerweile habe ich herausgefunden, das die "Parallel.For" einige Thread-Zyklen den LocalState mitspeichert und nach "Hausnummer 10" die localstates zusammenzählt, egal wieweit die Schleife ist, und dann wird der LocalState neu initialisiert.

Somit stellt sich für mich die Frage, wie kann ich einem Thread einmal ein Objekt mitgeben, das den ganzen Lebenszyklus des Thread hindurch nicht verändert wird. Das Objekt muss zur Erstellung des Thread erzeugt und beim Zerstören des Threads zerstört werden => Somit ist der LocalState dafür nicht geeignet! Außerdem darf das Objekt nicht geshared werden!

Weiß hier irgendwer wie man soetwas realisieren kann?

Hy@all,

ich habe ein Problem bei der Initalisuerung des ThreadLocalStates.

Ich möchte pro Thread einen Clone eines Objekt ablegen. Nun habe ich einfache eine Init-Methode für den ThreadLocalState geschrieben, die diesen Clone erstellt und im localState zu Verfügung stellt. Nach dem Testen habe ich gesehen, das die Init-Methode öfters als die Anzahl der Threads aufgerufen wird - aber warum? Ich dachte bis jetzt das diese nur bei der Thread-Erstellung aufgerufen wird.

Hier der Testcode:


Parallel.For<double>(0, size, () => InitThreadLocalState(), (k, loop, localstate) =>
            {
                Vector3D r = new Vector3D(1, 0, 0);
                return localstate;

            },
            (localstate) =>
            {
                lock (localobj) { Sum += localstate; } }
                    );

Wenn diese Verhalten normal ist, wie kann ich dann meine Init-Methode nur zur Threaderstellung aufrufen?

MfG
Tonka

So, hab den "Fehler" jetzt gefunden. Es ist tatsächlich der Zugriff auf das Scene3D-Objekt. Umso mehr Zugriff auf Scene3D ausgeführt werden umso langsamer wird das Programm. Das einzige was mir einfällt ist, für jeden einzelnen Kern einen Klon des Scene3D-Objekt zu erstellen (und im ThreadLocalState speichern) um keine gemeinsamen Resource zu nutzten!

Ist diese Annahme falsch?

du hast hier mehrere mögliche Ursachen und du hast nicht eine einzige bislang ausschließen können...

Welche sollten das sein, das lock'en für den Fortschrittszähler hab ich scho ausgeschlossen, das auslösen des Events habe ich ebenfalls auskommentiert und alle schreiben Zugriff sind deaktiviert => Ergebnis: Einfluss nicht Nennenswert. Das einzige was übrig bleibt ist das Scene3D Objket, auf das nur lesend zugegriffen wird. Ein tracer ist ja eigentlich sehr simpel aufgebaut

1.) Lese Strahl aus Datei ein
2.) Verschneide alle Dreiecke mit dem Strahl und gib mir das näheste Dreick zurück
3.) berechnen Brechung/Reflexion/Absorbition etc.
4.) generiere neuen Strahl
5.) widerhole Schritt 2 bis 4 bis kein Dreieck mehr getroffen wird

Die Schritt 1 bis 4 greifen lesen auf Scene3D zu, auf sonst nichts. Der Schritt 2 bis 4 wird tausendemale aufgerufen

Welche Fehlerursachen bleiben da noch über?

Naja, das Problem ist ja schon lokalisiert, ich habe nur ein großes Scene3D-Objekt, das sich die Threads teilen, alle anderen Variablen werden lokal in den einzelnen Threads erstellt.

Ich verstehe ja das Problem, hab nur nicht die gerinste Ahnung wie ich das anderes schreiben könnte.

Jetzt hab ich schon davon gehört 😄

Ok, so in der Art hab ich mir das schon gedacht, jedoch fällt mir nicht wirklich ein Lösung für das Problem ein. Muss ich das Scene3D Objket in seine Einzelteil aufspalten, oda wie kann ich diesem Problem entgegenwirken?

eben drum kann es ja passieren, dass die Threads sich gegenseitig aus dem (gemeinsam benutzen L2-)Cache werfen. Würden alle die gleichen Daten benutzen, würde das ja gerade nicht passieren.

Das verstehe ich jetzt nicht ganz. Ist das Objekt Scene3D (in dem alle Dreiecke, Strahlen, etc. gespiecher sind) das Problem, da die Threads die Funnktionen und somit die Daten des Objekts benutzten?? Wenn ja, wie kann man sonst die ganzen Daten zu Verfügung stellen.

MfG

Versuche es auch mal in einem Performance-Profiler. Der kann die sagen, wo Wartezeiten entstehen bzw kann er einem hinweise darauf geben.

Den probiere ich gerade aus - ich kann jedoch leider die Option "Verhalten der Multithreadanwendung visualisieren" aktiveren => "Erfordert Infrastruktur, die unter dieser Version von Windows nicht verfügbar ist". Ich habe WinxP x64, das ist vermtulich das Problem => kann man da irgendetwas nachinstallieren?

Gibts für den "Concurrency Visualizer" irgendwo eine gute Beschreibung, ich blick da momentan nicht so durch?

Gründe, warum ein Multithreading-Programm langsamer laufen kann als ein Singlethreading-Programm gibt es viele. Im einfachsten Fall wirft der aktuelle Thread immer gerade die Daten aus dem Cache, die der nächste Thread brauchen wird. Ob das bei dir der Fall ist, weiß ich nicht. Aber denk mal in Richtung solcher und ähnlicher Konflikte.

Das es genügen Gründe gibt ist klar 😃. Wenn ich das Schreiben auf die Sensoren weglasse, so gibt es (aus meiner Sicht) keine gemeinsamen Daten, das was einer der Threads berechnet interessiert den anderen eigentlich nicht (RayTracen gilt ja als Hochparallelisierbar) oder spricht du von anderen Daten? Könnte das große Szenenobjekt (kann schon mal 1 bis 2GB groß sein) ein Problem sein, es wird von dort gelesen aber nicht geschrieben?

limitierener Faktor kann auch die Festplatte sein, sowie Synchronisierungs-Overhead.

Festplatte, es wird bei mir alles in den Arbeitsspeicher geschrieben! Meinest du den "Synchronisierungs-Overhead" der Threads?

Du hast z.b. die Sache mit dem Filestream drinn.. Ist zwar nur bei DEBUG variablen aktiv aber ohne diese Varaible, kompiliert dein Code nicht... Daher vermute ich mal, das du es noch nicht ohne hast laufen lassen?

Das verstehe ich nicht ganz, wenn die DEBUG -Konstante gesetzt ist ist der BinaryWriter immer null und wird auch nicht genutzt, da in der TraceRay-Funktion ebenfalls eine #if eingebaut ist!

Weiter wirfst du ein Event. Wenn in diesem Die UI geupdated wird, mit z.b. Invoke, dann entstehen hier unnötige Wartezeiten für jeden Thread.

Das passiert momentan nur alle 1000 abgearbeiteten Strahlen. Gibts hierfür eine bessere Lösung? Ich brauch den Fortschrittbalken, den manche Simulation laufen bis zu 3 Tage!

VS hat auch nen prima Tool um sowas zu analysieren:
Concurrency Visualizer

Danke für den Tipp, werd ich mir mal anschauen.

Hy@everybody,

ich arbeite schon seit ca. einem Jahr an einem RayTracer (kein 0815 Tracer für Spiele, sonder ein physikalisch absolut korrekter Tracer).

Ich habe zwei Konfigurationseinstellungen für die Assemblies. Einmal "SingleCore" und einmal "MultiCore". Die Funktionen (und deren Geschwindigkeit) des Tracers werden im SingleCore - Modus geschrieben/geprüft. Im MultiCore versuche ich diese zu Parallelisieren.

Mein Problem ist folgendes: Ich schaffe es nicht die einzelnen Kerne zu 100% zu belasten (dass das nicht exakt möglich ist ist mir schon klar 😃 ). Jeder Kern (auf meiner Maschine 4 Kerne) werden nur zu ca. 60% ausgelastet. Nun habe ich den Effekt, das meine SingleCore-Variante fast doppelt so schnell ist wie die MultiCore-Variante und für mich ist das ein großes Rätsel. Ich habe schon einige Sachen ausprobiert, es hat aber leider nicht zu einem wirklichen Erfolg geführt.

Meine erste Vermutung war, das die Threads zu schlecht ausgelastet sind, somit habe ich einem Thread mehrere Strahlen gegeben => Änderung 0

Ich habe die schreibenden Zugriffe (die Sensoren) auskommentiert => Änderung 0

Für mich ist das echt ein Rätsel. Hier eine kurze Erklärung meines Programms:
Aus einem sehr bekannten CAD-System werden Geometrieobjekte in Dreiecke konvertiert (gemesht) und in eine XML-Datei geschrieben. Diese Datei wird dann von meinem Tracer eingelesen und in einem großen Objekt (class Scene3D) gehalten. Im Scenen-Objekt ist auch ein spezieller Strahlengenerator, der aus Dateien Strahldaten einliest und dem Tracer zu Verfügung stellt. Jeder einzelne Strahl wird in die Scene geschickt und getract. Sollte ein Strahl einen Sensor treffen, so wird die logischerweise gespeichert.

So, hier nun meine zwei Code-Variante:
-) SingleCore


this.traceInfo.Multithreading = false;
                TraceInfo localInfo = this.traceInfo;// trace-information, ob z.B. manche Strahlgänge nicht berechenbar sind
                for (Int32 k = 0; k < CountOfRaysForIteration; k++)
                {                    
                    if (IsCancel)// abfrage für cancel
                    {
                        break;
                    }
                    RayCalculation ray = null;
                    this.Scene.Source.GetRay(k, ref ray);// von der Scene wird der zu berechnende Strahl ermmittelt
                    ActualRayCount += ray.RepeatTime;//wieviele rays sind bis jetzt simuliert worden

                    TraceRay(ray, RefractionIndexEnvironment, AbsorptionCoefficientEnvironment, ref localInfo,bw);//die Hauptfunktion, hier wird ein Strahl in die Scene geschickt und verfolgt (trace)
                    
                    if (ActualRayCount % RayCountEventTick == 0)//alle n Strahlen wird ein Event für den Fortschrittsbalken ausgelöst
                    {
                        OnRayCountTick(new RayCountEventArgs(ActualRayCount));
                    }
                } 

-) MultiCore


this.traceInfo.Multithreading = true;
                Object localobj = new object();


                try
                {
                    //for (Int32 k = 0; k < CountOfRaysForIteration; k++)
                    Parallel.For<TraceInfo>(0, CountOfRaysForIteration, () => new TraceInfo(), (k, loop, localstate) =>
                    {
#if DEBUG
                        FileStream fss = null;
                        
#endif
                        BinaryWriter bww = null;
                        try
                        {
                            if (IsCancel)
                            {
                                loop.Break();
                            }
#if DEBUG
                            fss = new FileStream(Scene.OutputDirectory + Scene.SimulationParameters.SimulationName + ".lef", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write);
                            bww = new BinaryWriter(fss);
#endif
                            ////
                            RayCalculation ray = null;
                            this.Scene.Source.GetRay((int)k, ref ray);
                            lock (localobj) { ActualRayCount += ray.RepeatTime; }
                            TraceRay(ray, RefractionIndexEnvironment, AbsorptionCoefficientEnvironment, ref localstate, bww);
                            if (ActualRayCount % RayCountEventTick == 0)
                            {
                                OnRayCountTick(new RayCountEventArgs(ActualRayCount));
                            }
                        }
                        catch (Exception ex)
                        {
                            throw ex;
                        }
#if DEBUG
                        finally
                        {
                            if (bww != null)
                            {
                                bww.Close();
                                bww = null;
                            }
                            if (fss != null)
                            {
                                fss.Close();
                                fss = null;
                            }
                        }
#endif

                        return localstate;
                    },
                        (localstate) => { lock (localobj) { traceInfo += localstate; } }
                    );
                }
                catch (AggregateException ex)
                {
                    String Text = "";
                    foreach (Exception e in ex.InnerExceptions)
                    {
                        Text += e.Message + "\n";
                    }
                    throw new Exception(Text);
                }

Hatte jemand schon mal ähnliche Probleme?

MfG
Tonka

Hy,

mir ist soetwas was du brauchst auch nicht bekannt.

Vorschlag: Mache deine eigene Timerklasse (abgeleitet von System.Timers.Timer).

Variante 1: Als Member speicherst du eine StopWatch, die du nach jedem Tick Resetest und dann wieder startest.

Variante 2: Als Member speicherst du die Zeit vom letzten Tick. Wenn du dann deine Methode(die Methode für "wie weit bin ich") aufrufst kannst du dann die aktuelle Zeit von der LastTickTime subtrahieren und dann hast du auch ein TimeSpan.

MfG
Tonka

@Talla: Hba jetzt den Breakpoint auf "throw ex" gesetzt => das system geht dann zu den exceptions weiter. Wenn ich ohne Debugger starte wird die Exception nicht dargestellt und catch ganz normal aufgerufen.

@Schlopp: Ja, das irritiert mich 😉

Das heißt, das ich ein "normalen" Ablauf nur ohne Debugger erreiche, mit Debugger muss ich die Exception mit "F5" weiterdrücken => Stimmt das?

komisch, habs gerade bei meinem Kollegen ausprobiert, der hat das selbe Problem wie ich. Gibt es irgendwelche Einstellungen die man in VS ändern muss?

Habe kurz ein Testconsole-App geschrieben.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ParallelTest2
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Int32 GlobalState = 0;
                Object locker = new Object();
                const Int32 CountOf = 100000;
                Parallel.For<Int32>(0, CountOf, () => 0, (k, loop, localstate) =>
                    {
                        throw new Exception("Error-Test");
                        return localstate;
                    },
                    (localstate) => { lock (locker) { GlobalState += localstate; } }
                );
            }
            catch (AggregateException ex)
            {
                string a = "";//<- hier komme ich nicht
            }
        
        }
    }
}

Der Effekt bleibt!

wenn die Parallel.For-Schleife im GUI-Thread aufgerufen wird dann blockiert sie diesen solange bis die Schleife fertig ist. Also bei GUI die Parallel.For in einem Task.StartNew aufrufen.

Genau das habe ich ja.

Hallo,

CountOf ist nicht 0! Kann das eventuell daran liegen, das die Parallel.For nocht in einem eiegenen Task steckt (non-gui)?

Habe kurz ein Test-Consolen-Programm geschrieben, dort habe ich den gleichen Effekt!

Hy@all,

ich habe gerade testhalber eine Exception innerhalb einer Parallel.For geworfen, um wie in den Doku's beschriebenen AggregatException zu testen. Jedoch kann ich die Exception nicht (ab)fangen => Wieso?

Hier ist der TestCode:


try
                {
                    Parallel.For<Info>(0, CountOf, () => new Info(), (k, loop, localstate) =>
                    {                        
                            throw new Exception("Test-Error");
                        return localstate;
                    },
                        (localstate) => { lock (localobj) { globalInfo += localstate; } }
                    );
                }
                catch (AggregateException ex)
                {
                    string a = "";
                }
                catch (Exception ex)
                {
                    string b = "";
                }

Im Codebeispiel von MS stehts auch so

MfG
Tonka

Ich weiß es ist gemein im Nachhinein, aber so stehts auch in der Doku zu der entsprechenden Funktionsüberladung 😉 Also das der localState einmal pro Thread erstellt wird etc.

Keine Angst, das find ich nicht gemein, ich habe scheinabr die falschen Tutorials angesehen, da stand das nicht, bei MS-Beispielen stehts drin. Danke für den Link

MfG

Hallo Talla,

danke für deine Antwort, das ist die Lösung. Die Erklärung klingt, im nachhinein 😉, sehr logisch. Ich fasse das kurz in meinen eigenen Worten zusammen:
Pro Thread merkt man sich mittels localstate die internen Werte. Dadurch das der Thread wiederverwendet wird (Threadpool) darf ich diese Variable nicht neu instanzieren, da ja ansonst das alte Objekt überschrieben wird. Wenn alle Iterationen fertig sind, werd die Aggregation ausgeführt sprich zählt die localstates der einzelnen Threads zusammen.

Sehr interessant, das habe ich leider bei keinem der Tutorials gelesen.

Danke für die Info.

MfG

Hy@everybody,

ich arbeite schon seit einiger Zeit an einem RayTracer. Bis jetzt läuft dieser als Single-Thread Applikation ab. Jetzt möchte ich diesen mittels TPL parallelisieren (ich habe noch nie mit der TPL gearbeitet). Ich habe dazu einige Tutorials und Videos angesehen und ich versuche gerade eine kleine Testinstanz zu basteln. Jetzt habe ich, aus einem mir nicht bekannten Grund, ein DataRace obwohl ich eigentlich "lock"e.

Kurze Beschreibung: Ich muss aus meinen Threads Datensammel (hier im Beispiel: wie viele Strahlen konnten nicht berechnet werden = "errorray", später werden es wesentlich mehr Daten sein als nur ein int).

Ich habe eine "Globale" Variable (GlobalInfo) die die Information zusammenzählen soll. Mein localstate heißt "localstate" 😉 .

Das Programm soll einfach nur alle errorrays in GlobalInfo zusammenzählen. In diesem Beispiel erzeugt jeder Thread 1 errorray. Das gesamte Ray-Array hat 10000 Strahlen. Bei der seriellen Abarbeitung kommt exakt 10000 heraus, bei der parallelen Variante kommt ein Werte zweischen 2 und 81 raus. Dies schaut mir eindeutig nach einem DataRace aus obwohl ich die Variablen beim Zusammenzählen gelockt habe. Wo habe ich hier einen Denk/Schreibfehler - denn in den Tutorials ist das mit dem LocalState immer so geschrieben worden.

Program.cs:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace ParallelTest1
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {

                Tracer tracer = new Tracer();
                tracer.Trace();
            }
            catch (Exception ex)
            {
                Console.WriteLine("error: " + ex.ToString());
            }
            finally
            {
                Console.WriteLine("ende");
                Console.ReadKey();
            }
        }
    }
}

Tracer.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ParallelTest1
{
    public class Tracer
    {
        public Boolean Trace()
        {
            Rays rays = new Rays();
            for (long i = 0; i < 10000; i++)
            {
                rays.Add(new Ray());
            }

            Console.WriteLine("Parallel:");

            object lockobj = new object();
            TraceInfo GlobalInfo = new TraceInfo();
            
            Parallel.For<TraceInfo>(0, rays.Count, () => new TraceInfo(), (j, loop, localstate) =>
            {
                localstate.errorrays = TraceRay(rays[j]);
                return localstate;
            },
               localstate => { lock (lockobj) { GlobalInfo += localstate; } }
           );

            Console.WriteLine("errorrays: " + GlobalInfo.errorrays.ToString());

            Console.WriteLine("\nSerial:");

            GlobalInfo = new TraceInfo();

            for (int i = 0; i < rays.Count; i++)
            {
                TraceInfo info = new TraceInfo();
                info.errorrays = TraceRay(rays[(int)i]);
                GlobalInfo += info;
            }
            Console.WriteLine("errorrays: " + GlobalInfo.errorrays.ToString());

            return true;
        }

        public int TraceRay(Ray ray)
        {
            return 1;//sim 1 error
        }
    }
}


PObject.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ParallelTest1
{
    public class PObject
    {
        public TraceInfo Info;

        public PObject()
        {
            Info = new TraceInfo();
        }
       
    }

    public class TraceInfo
    {
        public long errorrays = 0;

        public static TraceInfo operator +(TraceInfo a, TraceInfo b)
        {
            TraceInfo n = new TraceInfo();
            n.errorrays = a.errorrays + b.errorrays;
            return n;
        }
    }
}


MfG
Tonka

Gegen Sharepoint spricht grundsätzlich nicht viel.

Hab mich aber momentan für ein einfache Wiki entschieden. Dort werden der User-Guide und die Developer-Section geführt.

BugReport wird über einen eigenen Track realisiert.

Sharepoint (SHarePoint-Foundation) habe ich als Testinstanz auch laufen, um es nebenbei mal zu testen 😉

Das ist nicht üblich, da in einem Bucktracking System üblicherweise die technische Beschreibung und Kommentare der Entwickler stehen (was ja wichtig und korrekt ist). Der Standard-User ist mit sowas überfordert.

Ich meinte eigentlich nur das man bekannte Bugs ala "Bitte diesen Button nicht drücken" zu den Features dazuhängen kann, nicht den Bug-Report selbst!

Die Eierlegendewollmilchsau gibt es nicht.

Das ist mir klar 😉

du musst dich entscheiden, ob das ganze Getrennt wird oder in einen Topf geworfen wird, denn sonst lässt sich keine Empfehlung geben.

Um das geht es mir ja in diesem Thread, welche System gibt es und was können die - und gibt es bereits User in diesem Forum die Erfahrung mit dem ein oder anderen System haben.

Das Projekt wurde schon mit MS Project gelpant.

@Arithmetika: Das Ganze wird auf jeden Fall getrennt stattfinden! Die Architektur wird sowieso "extern" (nicht im Web) geplant, ich meinte nur das die Architektur angezeigt wird z.B. in einem Bild oder ähnliches. Gleiches gilt für das Gantt-Diagramm, es soll mit der Web-Oberfläche nicht editiert, sondern nur Dargestellt werden (z.B. wichtige Versionssprünge etc.) - am besten wäre es wenn man es von MS Project importieren können (ist aber kein Muss).

Zum User/Installations-Guide: Mit CHM wäre es möglich. Die Software wird nur innerhalb unserer Firma verwendet, somit ist mir hier eine Art Wiki-System lieber.

Zum Bug-Tack: Es wäre toll, wenn man die BUgs zu den Features in den Userguide übernehmen könnten, denn dann sehen die User das dort noch Bugs sind!

Die Doku sollte folgendes umfassen:

-) User-Guide
-) Installation Guide

Optional:
-) Bug Track
-) Gantt Diagramm
-) Architektur
-) Feature
-) Projektfortschritt

etc.

Redmine schaut eigentlich schon sehr gut aus, schon wer Erfahrungen damit?

Hallo,

ich arbeite gerade an der Planung eines relativ großen Projektes. Nun bin ich gerade dabei, welche Möglichkeiten ich habe, um eine vernüpftiche Dokumentation (keine Code-Doku wie es z.B. GhostDoc und co machen!).

Die Software sollte folgendes können:
-) Reversionieren wie z.B. SVN/Wiki
-) mehrere User können die Doku gleichzeitig editieren (wie ein Content-Managament)
-) PDF sollte nach Möglichkeit direkt ausleitbar sein

Mir sind bis jetzt nur zwei Möglichkeiten eingefallen:
-) Word mit SVN (ist nicht gerade mein Favorit)
-) eine umgebautes Wiki System

Kennt bzw. benutzt ihr System mit denen so ein Funktionsumfang möglich ist - zumindest teilweise - egal ob Freeware, OpenSource oder kommerzielle Software ???

MfG
Tonka

Hallo,

vielleicht hilft dir das weiter!

MfG
Tonka

Was du suchst heißt Impersonation. Hier ist ein Artikel beim CodeProject. Mit diesem Code ist es möglich, mitten im Code/Programm die Identität zu wechseln - aber geh damit behutsam um, den wen du dich von der Impersonierung nicht ausloggst (z.B. Exception nicht sauber behandelt) läuft das Programm weiterhin unter einem anderen User => Sicherheitslücke!

Ich hoffe ich konnte dir helfen!

MfG
Tonka