Autor Beitrag
Mayhem
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Sa 19.07.14 23:35 
Hey Comunity :)

Ich versuche mich gerade an einem kleinem Projekt und habe folgendes Problem:

Ich habe ein WPF Projekt mit Microsoft Visual C# 2010 (Zielframework: .NET Framework 4 Client Profile) aufgesetzt und mit 2 Textboxen sowie 2 Buttons versehen...

Die Textboxen sind für Start und Ende gedacht...
Der Erste Button führt die Schleife Von "Start" bis "Ende" aus.
Und der zweite Button gibt eine MessageBox aus.

Jetzt möchte ich, dass der erste Button meine While-Schleife startet aber die UI nicht freezt und man den zweiten Button, der eine MessageBox ausgibt weiterhin klicken kann... Das krieg ich aber irgendwie leider nicht hin... :(

Hoffe, dass ihr mir weiterhelfen könnt oder einen Link zum lesen habt ;)
Ich finde nämlich irgendwie nichts... suche jetzt schon 2 Tage nach einer lösung dafür...
Oder ich bin einfach zu dämlich für Google & Suchfunktionen ^^''

Danke im Vorraus für eure Antworten!
Mayhem

Hier mal der Code von der MainWindow.xaml:
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace whiletest
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            var worker = new BackgroundWorker();
            worker.DoWork += worker_DoWork;
            worker.RunWorkerAsync();
        }
        private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            int i = 0;
            this.Dispatcher.BeginInvoke(new Action(delegate()
            {
                while (Convert.ToInt32(textBox1.Text) < Convert.ToInt32(textBox2.Text))
                {
                    textBox1.Text = i.ToString();
                    i++;
                }
            }));
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Ich bin eine MessageBox");
        }
    }
}


und hier die SRC's des Projekt's:
85.214.124.247/whiletest.zip

Moderiert von user profile iconTh69: Code- durch C#-Tags ersetzt
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: So 20.07.14 10:21 
Hallo und :welcome:,

du hast bei deinem Code ein bißchen zu viel des Guten eingesetzt. ;-)

Zum einen solltest du den BackgroundWorker und den Dispatcher nicht mixen. Der eigentliche Fehler aber ist, daß du durch den Aufruf von Dispatcher.BeginInvoke innerhalb der BackgroundWorker.DoWork-Methode wieder die Ausführung in den GUI-Thread verlagerst hast (so daß dieser dann blockiert).

Als Links kann ich dir die beiden FAQs aus dem myCSharp-Forum empfehlen:
[FAQ] Warum blockiert mein GUI?
[FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke)

Für dein jetziges Problem würde ich dir jedoch einen Timer empfehlen, für WPF den DispatcherTimer.
Mayhem Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Mo 21.07.14 03:36 
Hey :)
Danke für deine Antwort.
Leider verstehe ich nicht, wie mir da ein Timer helfen kann :o
Hättest du vielleicht ein kleines Beispiel, wie es mir in dem Zusammenhang helfen kann?
- Bin leider noch ein kleiner Anfänger im programmieren :)

Das ich durch das Invoke den Thread zurück an die GUI sende, wusste ich bereits ;)
Ich hätte vielleicht besser beschreiben sollen, was mein Problem ist ^^

Problem ist halt, dass ich ohne das Invoke leider nicht auf die TextBoxen zugreifen kann und eine Fehlermeldung ausgelöst wird, was ja aber auch klar ist, weil ich vom Thread aus auf die GUI zugreifen will.

Jetzt möchte ich halt gern wissen, wie ich auf die TextBoxen der GUI zugreifen kann, ohne ein Invoke ausführen zu müssen, weil ja sonst die GUI wieder freezt ^^

Hoffe es ist jetzt etwas klarer und danke weiterhin für jeden tipp :)
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mo 21.07.14 09:20 
Hallo Mayhem,

deine jetzige Schleife blockiert das gesamte Programm, weil du damit die Prozessorlast (bzw. Kernlast) auf 100% setzt, da du keine Wartefunktion drin hast (z.B. ein Thread.Sleep()).
Was genau möchtest du denn mit deiner Schleife erreichen (denn bisher zählt das Programm, so schnell der Rchner kann, den Zähler hoch und gibt ihn in der TextBox aus - und das blockiert halt!)?

Ein Timer hilft, daß eine wiederkehrende Aufgabe (z.B. die Ausgabe) mit einen bestimmten Intervall (z.B. jede 1/10 Sekunde, jede Sekunde oder auch jede Minute etc.) ausgeführt wird. Der Anwender kann sowieso nicht mehr als ca. 25 Änderungen pro Sekunde verfolgen (entspricht ca. den Filmframes)!

PS. Ein Invoke wirst du bei jeder GUI-Aktion aus einem anderen Thread ausführen müssen. Ein Timer dagegen läuft im selben Thread, d.h. da brauchst du kein Invoke!
Mayhem Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Mi 23.07.14 19:46 
Hey Th69,
erstmal sorry, dass ich so lang auf meine Antwort hab warten lassen (Hatte viel zu tun)...

Danke für die Erklärung!
Ich werde mir das ganze dann nochmal mit nem (Dispatcher)Timer anschauen und testen.
Falls ich nicht weiter komme, meld ich mich wieder :)

Zitat: " Ein Timer dagegen läuft im selben Thread, d.h. da brauchst du kein Invoke! "

Das wusste ich zum Beispiel noch nicht...
Ich dachte ein Timer blockiert genauso ^^''

Man lernt immer was dazu!

Danke nochmal für die Hilfestellung :D