Laden...

Animation aus Threadpool Thread

Erstellt von High End Gaming PC Freak vor 13 Jahren Letzter Beitrag vor 13 Jahren 1.471 Views
H
31 Beiträge seit 2008
vor 13 Jahren
Animation aus Threadpool Thread

Hi ihr Programmierer da draußen,
nach langem probieren bin ich leider verzweifelt und habe mich entschieden, dass ich trotz vieler Informationen zu diesem Thema einen eigenen Thread eröffnen muss.

Folgende Situation: Ich möchte aus einem Threadpool Thread eine PointAnimation einer Ellipse in einem canvas control ausführen. Die Methode, die die entsprechenden Sachen ausführt befindet sich dabei in einer Klasse. Meine Versuche mit Invoke() haben bisher keine Früchte getragen. Immer wieder wird mir gesagt, das ein Objekt nicht zu meinem Thread gehört (welches ist dabei nicht zu lokalisieren, auch nicht mit Step by Step Debug).

Ich denke, zur Veranschaulichung ist dabei ein isoliertes Stückchen Quellcode von Nöten.


namespace CrossThreadCall
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Klasse k = new Klasse(canvas1);
            ThreadPool.QueueUserWorkItem(new WaitCallback(k.Machen));
        }
    }
}

//=========die Klasse==========

namespace CrossThreadCall
{
    class Klasse
    {
        delegate void Zeichnen(object context);
        Canvas Fläche;
        EllipseGeometry ellipse; 
        public Klasse(Canvas ctrl)
        {
            Fläche = ctrl;
        }

        public void Machen(object context)
        {
            Point a = new Point(5, 5);
            Point b = new Point(300, 100);

            EllipseGeometry myEllipseGeometry = new EllipseGeometry();
            myEllipseGeometry.Center = a;
            myEllipseGeometry.RadiusX = 5;
            myEllipseGeometry.RadiusY = 3;

            PointAnimation ani = new PointAnimation();
            ani.Duration = TimeSpan.FromSeconds(10);
            ani.From = a;
            ani.To = b;
            object carrier = new object();
            carrier = ani;
            ellipse = myEllipseGeometry;
            ZeichnenKlasse(carrier);
        }

        public void ZeichnenKlasse(object Inhalte)
        {
            if (Fläche.Dispatcher.CheckAccess() == false)
            {
                Fläche.Dispatcher.Invoke(new Zeichnen(ZeichnenKlasse), Inhalte);
                return;
            }
            PointAnimation ani = (PointAnimation)Inhalte;
            Path myPath = new Path();
            myPath.Fill = Brushes.Red;
            myPath.Margin = new Thickness(15);
            myPath.Data = ellipse;
            Fläche.Children.Add(myPath);
            ellipse.BeginAnimation(EllipseGeometry.CenterProperty, ani);
        }
    }
}

Ich habe dabei eine Ellipse global in der Klasse definiert, da ich mit Invoke keine Objekt Arrays weiterreichen kann. Ich hoffe, dass ihr den Wald und nicht nur die Bäume seht und vllt. habt ihr sogar einen Tip, wie ich den Vorgang verbessern könnte.

Mfg,
HEGPCF

PS: Warum zur Hölle steht CheckAccess() nicht in Intellisense? Ich hab mich totgesucht 🤔

Auch wenn es nicht den Anschein hat
Ja, ich kann programmieren.
Zu guter letzt:
It's not a bug, it's a feature

Gelöschter Account
vor 13 Jahren

Wie kommst du darauf das du eine WPF Animation in einem Thread starten musst?

1.044 Beiträge seit 2008
vor 13 Jahren

Hallo High End Gaming PC Freak,

bei Animationen in WPF brauchst du keine Threads zu erstellen. Das alles übernimmt WPF intern. Du musst lediglich die Animation angeben und starten. Am besten machst du das im XAML-Code. Im Code ist das alles sehr aufwenig. Warum möchtest du überhaupt die Animation als C#-Code schrieben? Das hat absolut keine Vorteile. Schreib das direkt im XAML.

zero_x

H
31 Beiträge seit 2008
vor 13 Jahren

Die Animation wird Teil einer Schwarmsimulation, in der ich mehrere Agenten parallel laufen lassen will. Diese müssen dazu autonom handeln und eben auch ihre Position ändern. Diese Änderung verläuft in jeweils einem eigenem Thread für jeden Agenten. Die Animation muss nicht zwangsweise in der Klasse als Methode stehen, da man aber per Event die Animation aus dem Thread heraus ebenfalls nicht starten kann, habe ich sie vorerst da reingeschrieben.

Das allgemeine Problem (egal wo die Methode steht) bleibt aber leider 🙁

Mit XAML habe ich bisher überhaupt keine Erfahrung und ich bin mir nicht sicher, ob es den Zweck erfüllen würde (Änderungen der Informationen zur Laufzeit, XAML ist doch statisch, oder?)

Auch wenn es nicht den Anschein hat
Ja, ich kann programmieren.
Zu guter letzt:
It's not a bug, it's a feature

6.862 Beiträge seit 2003
vor 13 Jahren

Hallo,

Animationen laufen schon vollkommen asynchron. Da muss man wie JAck30lena schon sagt nichts in nen Thread packen.

Das Problem ist aber bei deinem Code trotzdem leicht zu finden. Du erstellst in nem Thread die Animation, dadurch hat sie nicht den gleichen Dispatcher wie das zu animierende Objekt und dann kannst du Invoken wie du willst, dadurch ändern sich die Dispatcher nicht und es knallt mit deiner beschriebenen Fehlermeldung. Es gibt ne Lösung, Stichpunkt Freezable.

XAML als Beschreibung ist schon statisch im gewissen Sinne, aber das ist deine Animation auch im Code. Parameter der Animation kann man so oder so ändern.

Und wenn du keine Erfahrung mit XAML hast, dann guck das du welche sammelst. WPF geht nicht ohne XAML.

Baka wa shinanakya naoranai.

Mein XING Profil.

H
31 Beiträge seit 2008
vor 13 Jahren

Die Frage für mich ist nur, wie bekomme ich die Informationen aus dem Thread, in dem die Methode meiner Klasse läuft, in eine Animation gepackt, sodass ich sie ohne Fehler aufrufen kann.

Per Event habe ich es schon probiert, wenn ich in dem Event die Animation starte hat es auch nicht geklappt. Bin eben noch recht unerfahren in dem Bereich. Ich arbeite gerade daran, das zu ändern 😁

Edit: Das Animationen async laufen ist gut zu wissen 😉

Auch wenn es nicht den Anschein hat
Ja, ich kann programmieren.
Zu guter letzt:
It's not a bug, it's a feature

6.862 Beiträge seit 2003
vor 13 Jahren

Hallo,

Du hast ja im Code dein Datenobjekt welches deinen Agenten repräsentiert. Der hat entsprechende Properties die du animieren möchtest. Nun musst einfach in XAML einmal für so nen Agenten nen Style definieren der ein Storyboard mit der Animation enthält. Die Animation nutzt DataBinding um gegen die Properties des Agenten zu binden und mit dem passenden Trigger im Style kannst du die Animation dann starten. Um die Agenten anzuzeigen musst du dann nur noch nen Control benutzen was eine Menge an Objekten anzeigt, sprich am besten wohl nen ItemsControl und für die Items verwendest du den Style den du definiert hast.

Wenn du sagst du bist noch recht unerfahren in WPF, dann schau dir unbedingt Grundlagen wie Databinding und Styles an. Ohne das geht gar nichts in WPF.

Baka wa shinanakya naoranai.

Mein XING Profil.

H
31 Beiträge seit 2008
vor 13 Jahren

Hmm, deine Hinweise sagen mir zwar etwas vom Verständnis her, aber codetechnisch habe ich einfach mal gar keinen Plan. 8) Das kann ich mir ja immernoch anlesen.

Was ich nicht verstehe ist dein letztgenanntes ItemControl. Wozu ist das denn da?

Gibt es sonst keine Möglichkeit, dass mit normalem C# Code zu machen? Ich glaube, dass das die einzigste WPF/XAML Problematik ist, die ich in dem ganzen Programm haben werde. Ich würde mich gern auf den Rest konzentrieren. Klar kann man immer sagen, dass man das lernen muss um es überhaupt zu probieren, ich sage aber mal: Erst was suchen, was ich sofort umsetzen UND verstehen könnte als einen großen Aufwand zu betreiben. Das nennt man effektiv (auch wenn es nicht schön ist 😉)

Ich schaue mir das Storyboard und freeze nochmal genauer an, habe es grade etwas aus den Augen verloren.

Mfg,
HEGPCF

PS: Ich hoffe auf weitere gute Ideen. Die Arbeit will ich nicht gemacht haben. Ich brauche Ansätze 😁

EDIT:

Du erstellst in nem Thread die Animation, dadurch hat sie nicht den gleichen Dispatcher wie das zu animierende Objekt und dann kannst du Invoken wie du willst, dadurch ändern sich die Dispatcher nicht und es knallt mit deiner beschriebenen Fehlermeldung.

Das wars. Aber etwas abgeändert. Ich erstelle die Animation in einer anderen METHODE als ich sie abspiele. Habe jetzt mal alles in eine Methode gepackt. Scheint zu gehen. Ich überprüfe das nochmal. Bei Erkentnissen poste ich nochmal den neuen Code hier rein.

Auch wenn es nicht den Anschein hat
Ja, ich kann programmieren.
Zu guter letzt:
It's not a bug, it's a feature

H
31 Beiträge seit 2008
vor 13 Jahren

Die Lösung des "ach so schweren" Problems scheint dann doch trivialer als Gedacht.

Der Post hier ist einfach mal ein Platzhalter, falls jemand den Code sehen möchte.

Auch wenn es nicht den Anschein hat
Ja, ich kann programmieren.
Zu guter letzt:
It's not a bug, it's a feature