Zum Inhalt springen

C# , FileSystemWatcher


Empfohlene Beiträge

Geschrieben (bearbeitet)

Deine Fragen lassen sich ganz leicht beantworten:

vor 5 Stunden schrieb Eleu:

Darf eine Klasse nicht von Form1 erben?

Doch.

vor 5 Stunden schrieb Eleu:

Wie kann ich aus einer Klasse heraus Methoden in der Form auslösen?

So wie mit jedem anderen Objekt auch.

Das hilft dir nur nicht. Daher kommt hier die Bitte (wiederholt), deinen gesamten Code mal zu zeigen, damit man dir erklären kann, wie du das, was du vorhast, am besten umsetzen kannst. Ich habe von dem, was du schreibst, so ein bißchen den Eindruck, als hättest du den Eindruck, die Form-Klasse sei irgendwas besonderes. Das ist sie nicht.

Wenn du eine Methode eines Formulars aufrufen möchtest, brauchst du als allererstes einen Verweis auf das Objekt:

Form1 myForm = new Form1();

Danach kannst du die öffentlichen Methoden dieses Objekts aufrufen:

myForm.Focus();

Wenn du jetzt aus einer Klasse, wie bspw. dem ResultWriter auf dein Formular zugreifen möchtest, ist die einfachste Möglichkeit, dieses im Konstruktor zu übergeben:

public ResultWriter(Form1 myForm)
{
 this.form = myForm; 
}

// und in einer anderen Methode dann:
this.form.Focus(); // wobei du Focus() natürlich durch deine Methode ersetzt

 

Bearbeitet von arlegermi
Geschrieben
vor 1 Minute schrieb Whiz-zarD:

Antwort auf welche Frage?

Ich sehe aber hier keine Frage.

Zitat

Noch eine technische Frage:

 

Wenn ich aus einer Klasse heraus in eine TextBox schreiben wollte, würde ich eine Methode dafür in der Form programmieren:

 


  public void TextAnzeigen()
  {
            textBox1.Text = "Der Text";
  }

Nun könnte ich ja in der Klasse einfach diese Methode aufrufen, wenn ich nun die Form1 als Basisklasse dort angebe

 


    public class ResultWriter : Form1

Die Methode ist in der Klasse dann auch aufrufbar, doch es funktioniert nicht. Ich bekomme beim Start der Anwendung diese Fehlermeldung:

System.StackOverflowException: "Eine Ausnahme vom Typ "System.StackOverflowException" wurde ausgelöst."

und zwar an dieser Stelle in der Form:


 ResultWriter b = new ResultWriter(); 

Danach hängt sich sogar das ganze Visual Studio auf und startet neu. Darf eine Klasse nicht von Form1 erben? Wie kann ich aus einer Klasse heraus Methoden in der Form auslösen?

 

Geschrieben (bearbeitet)

Die Frage wurde doch schon beantwortet. Was willst du denn noch?
Wenn du es nicht verstehst, dann stelle weitere Fragen und lass uns an deinen Gedanken teilhaben und stelle nicht einfach Codeschnippsel rein, bei denen wir nicht wissen, was du damit vor hast.

Bearbeitet von Whiz-zarD
Geschrieben (bearbeitet)

Den ganzen Code hier zu posten, wird etwas viel....

Aber ich kann den Fehler auch isoliert erzeugen:

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

namespace WindowsFormsApp1
{
    class Testklasse : Form1
    {
        public void Ausführen()
        {
            TextAnzeigen2();
        }

    }
}

Dann in der Form:

public Form1()
        {
            InitializeComponent();
		{

		}
            Testklasse ca = new Testklasse(); 

...

Und:

	public void TextAnzeigen2()
        {
            textBox15.Text = "Der Text";
        }



	private void button6_Click(object sender, EventArgs e)
        {
            ca.Ausführen();
        }

Wenn ich Starte, erfolgt die Fehlermeldung (Siehe Anhang)

Fehlermeldung.png

Bearbeitet von Eleu
Geschrieben

Ganz einfach:

Du hast in einer Form1 eine neue Instanz von Testklasse erstellt. Und zwar direkt in der Klasse...

Da du deine Form1 Klasse an Testklasse vererbst, wird diese Instantiierung erneut ausgeführt.

Du erstellst Testklasse, die von Form erbt und dadurch eine Testklasse erzeugt, welche auch von Form erbt, die eine Testklasse erzeugt usw. usw.

Du musst versuchen das anders zu lösen, zB. indem du die Testklasse nur in der Methode instantiierst, in der du sie benötigst.

Geschrieben
vor 6 Stunden schrieb r4phi:


 

(Ich bekomme die Zitat-box per Android nicht gelöscht) 

Die Frage wurde aber schon beantwortet. Du erzeugst eine Instanz von Form1. Die wiederum erzeugt eine Instanz von Testklasse und diese wieder von Form1, du wieder erzeugt eine Instanz von Testklasse, usw. usw. usw.

Du erzeugst also unendlich viele Instanzen von Form1 und Testklasse.  Irgendwann wir aber die Reißleine gezogen und das Programm schmeißt eine Stackoverflowexception

Geschrieben (bearbeitet)

Du hast dir mit dem Erben von Form1 eine Schleife gebaut.

Der Konstruktor der Klasse Testklasse ist nicht extra definiert. Er existiert dennoch und dieser ist im Prinzip wie folgt definiert:

public Testklasse() : base() {}

Vom Ablauf her:

  1. Testklasse-Konstruktor ruft durch die Vereerbung den konstruktor von Form1 auf
  2. Form1-Konstruktor erstellt ein neues Objekt vom Typ Testklasse mit dem Konstruktor. (zurück zu 1)

 

Edit: Da waren @KeeperOfCoffee und @Whiz-zarD etwas schneller. ;-)

Bearbeitet von Mttkrb
Geschrieben

Was sich mir noch nicht ganz erschließt, was auch noch nicht beantwortet wurde und das Problem eigentlich löst:

Warum zum Teufel ist deine Klasse TestKlasse() von Form1 abgeleitet?!?! :facepalm:

Ja. Man darf von Forms ableiten. Gibt einige Szenarien wo das durchaus Sinn macht.
Dieser Sinn ist hier aber in keinster Weise ersichtlich.

Geschrieben
vor 19 Minuten schrieb KeeperOfCoffee:

 

Du musst versuchen das anders zu lösen, zB. indem du die Testklasse nur in der Methode instantiierst, in der du sie benötigst.

  private void button6_Click(object sender, EventArgs e)
        {
            Testklasse ca = new Testklasse();
            ca.Ausführen();
        }

        public void TextAnzeigen2()
         {         
            textBox15.Text = "Der Text";
          }

Diese Variante funktioniert nicht. Wenn ich den Button betätige, wird die Methode TextAnzeigen2 nicht ausgeführt,

oder anders gesagt, es wird nichts in der TextBox15 angezeigt.

Geschrieben
vor 8 Minuten schrieb r4phi:

Was sich mir noch nicht ganz erschließt, was auch noch nicht beantwortet wurde und das Problem eigentlich löst:

Warum zum Teufel ist deine Klasse TestKlasse() von Form1 abgeleitet?!?! :facepalm:

Ja. Man darf von Forms ableiten. Gibt einige Szenarien wo das durchaus Sinn macht.
Dieser Sinn ist hier aber in keinster Weise ersichtlich.

Der Sinn der dahinter steht ist einzig und allein der, dass ich wissen möchte, ob es geht

Geschrieben (bearbeitet)
vor 56 Minuten schrieb Eleu:

Diese Variante funktioniert nicht. Wenn ich den Button betätige, wird die Methode TextAnzeigen2 nicht ausgeführt,

oder anders gesagt, es wird nichts in der TextBox15 angezeigt.

Das liegt wohl daran, sofern mit den Zugriffsmodifiern alles passt, dass du nicht die textbox1 von Form1 änderst, sondern die textbox1 von Testklasse, die ja auch eine Form ist ;)

gib in Testklasse einfach mal this.ShowDialog ein, dann solltest du beide Dialoge sehen. In einem steht dann was in der Textbox.

Oder anders gesagt: Ab Ausführen() änderst du Dinge in der Instanz der Testklasse und nicht in der Form1.

Du vererbst Form1 an Testklasse, trotzdem sind Form1 und Testklasse zwei unterschiedliche Objekte.

Bearbeitet von KeeperOfCoffee
Geschrieben

Um das ganze mal grafisch anschaulich darzustellen, was da passiert:

so.png.59fc62723275744122e248a87b0138e2.png

Du rufst über dein Program irgendwo ein new Testklasse() auf. Da Testklasse von Form1 abgeleitet ist, rufst du damit auch (implizit) ein new Form1() auf. Da du jetzt aber in Form1 auch immer eine neue Testklasse erzeugst (Testklasse ca = new Testklasse();), dreht sich das Programm im Kreis und es kommt zu dem von dir beobachteten Absturz.

Geschrieben
vor 18 Stunden schrieb KeeperOfCoffee:

gib in Testklasse einfach mal this.ShowDialog ein, dann solltest du beide Dialoge sehen. In einem steht dann was in der Textbox.

 

Hallo KeeperOfCoffee,

ja genauso verhält es sich dann. Wenn ich den Button betätige, wird die geerbte zweite Form (Testklasse) geöffnet und  dort erscheint dann auch der Text in der TextBox.

Grundsätzlich war eine Überlegung den FilsSystemWatcher in eine  extra Klasse auszulagern. Das würde dann aber imho bedeuten, dass diese Klasse dann zyklisch durchlaufen muss, sonst würde der FileSystemWatcher ja nicht arbeiten können, oder? 

Normalerweise ist es ja so, dass mir die Instanz einer Klasse erst dann einen Rückgabewert einer Methode, in der Klasse liefert, wenn ich dieses über ein Ereignis abfrage.

Momentan habe ich den FileSystemWatcher bei InitializeComponent() einprogrammiert. Ich verstehe es so, dass dieser Teil in der Form zyklisch abgearbeitet wird, genauso wie die Klasse Program.

Also kann man den FileSystemWatcher nicht in einer extra Klasse unterbringen, weil diese eben statisch sind?

Sehe ich das richtig? 

Gruß

Eleu

Geschrieben
vor 14 Minuten schrieb Eleu:

Normalerweise ist es ja so, dass mir die Instanz einer Klasse erst dann einen Rückgabewert einer Methode, in der Klasse liefert, wenn ich dieses über ein Ereignis abfrage.

Ich denke, Du bringst da verschiedene Sachen durcheinander. Schau Dir mal https://de.wikipedia.org/wiki/Ereignis_(Programmierung) an.

Man könnte Dich noch mehr verwirren, wenn man Dir noch von Threads erzählt.

Warum machen wir es aber nicht mal anders rum und fragen, was genau Du eigentlich genau ereichen willst und Du erzählst uns das dann Schritt für Schritt? Deine Ausführungen lesen sich momentan für mich so, als würdest du ausprobieren ob ein Elefant auch Rückwärts durch das Nadelöhr gezwängt werden kann - diese Vorgehensweise finde ich jetzt nicht sonderlich zielführend..

 

 

 

Geschrieben (bearbeitet)
vor 29 Minuten schrieb Eleu:

Grundsätzlich war eine Überlegung den FilsSystemWatcher in eine  extra Klasse auszulagern. Das würde dann aber imho bedeuten, dass diese Klasse dann zyklisch durchlaufen muss, sonst würde der FileSystemWatcher ja nicht arbeiten können, oder? 

Nein.

vor 29 Minuten schrieb Eleu:

Normalerweise ist es ja so, dass mir die Instanz einer Klasse erst dann einen Rückgabewert einer Methode, in der Klasse liefert, wenn ich dieses über ein Ereignis abfrage.

Der FileSystemWatcher arbeitet aber mit Events. Nicht mit Methoden. Das bedeutet das du nicht aktiv etwas abfragen musst. Der FileSystemWatcher meldet sich von selbst.

vor 29 Minuten schrieb Eleu:

Momentan habe ich den FileSystemWatcher bei InitializeComponent() einprogrammiert. Ich verstehe es so, dass dieser Teil in der Form zyklisch abgearbeitet wird, genauso wie die Klasse Program.

Nein. Wie kommst du darauf?
InitializeComponent() wird bei der Instanziierung deines Form Objekts aufgerufen.
Selbiges gilt für die Klasse Program... warum sollte diese zyklisch aufgerufen werden?

In einem normalen Forms Projekt sieht die Klasse so aus:

/// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }

Warum sollte dieses Code den zyklisch aufgerufen werden?
Setz einen Haltepunkt in dieser Klasse und schau wie oft dieser aufgerufen wird.

Application.Run startet eine Standardnachrichtenschleife einer Anwendung für den aktuellen Thread und zeigt das angegebene Formular an. Diese Schleife ermöglicht es dass das Form Windows Messages erhält. Mausklicks, gedrückte Tasten etc. um eben die Interaktion des Benutzers zu ermöglichen.

Wie der FileSystemWatcher funktioniert wurde doch in diesem Thread schon erklärt.

vor 29 Minuten schrieb Eleu:

Also kann man den FileSystemWatcher nicht in einer extra Klasse unterbringen, weil diese eben statisch sind?

Doch... warum sollte das den nicht funktionieren?
Ich verstehe auch nicht was du explizit am FileSystemWatcher auslagern möchtest.
Es ist doch im Prinzip schon eine eigene Klasse.

Bearbeitet von r4phi
Geschrieben

FileSystemWatcherWrapper

using System;
using System.IO;

namespace WindowsFormsApplication1
{
    public class FileSystemWatcherWrapper
    {
        public Action OnSomethingHappend;

        FileSystemWatcher _instance;
        private FileSystemWatcherWrapper()
        { }

        public FileSystemWatcherWrapper(string pathToMonitor)
        {
            this._instance = new FileSystemWatcher(pathToMonitor);
            _instance.Changed += (sender, e) => somethingHappend();
            _instance.Created += (sender, e) => somethingHappend();
            _instance.Deleted += (sender, e) => somethingHappend();
            _instance.Renamed += (sender, e) => somethingHappend();
            _instance.EnableRaisingEvents = true;
        }

        private void somethingHappend()
        {
            this.OnSomethingHappend?.Invoke();
        }

    }
}

Form1

using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private FileSystemWatcherWrapper _fileSystemWatcher;
        public Form1()
        {
            InitializeComponent();
        }

        public Form1(FileSystemWatcherWrapper fileSystemWatcher) : this()
        {
            this._fileSystemWatcher = fileSystemWatcher;

            fileSystemWatcher.OnSomethingHappend += () => MessageBox.Show("Something happend!");
        }
    }
}

 

Geschrieben

Hallo r4phi,

vielen Dank für den Code und ich habe ihn auch einmal einem ganz neuen Projekt ausprobiert.

Ich bekomme aber in der Form eine Fehlermeldung (Siehe Anhang)

Inkonsistenter Zugriff bei Form1.png

Geschrieben (bearbeitet)

Damit das ganze mit dem Wrapper in dem Context auch einen Sinn macht kannst du deinem Wrapper auch einen Logger übergeben:

Program.cs

static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1(new FileSystemWatcherWrapper(@"C:\temp", new DebugLogger())));
        }
    }

ILog.cs


    public interface ILog
    {
        void Log(string logMessage);
    }

DebugLogger.cs

   public class DebugLogger : ILog
    {
        public void Log(string logMessage)
        {
            Debug.WriteLine($"{DateTime.Now} :: {logMessage}");
        }
    }

FileSystemWatcherWrapper.cs

   public class FileSystemWatcherWrapper
    {
        public Action OnSomethingHappend;

        FileSystemWatcher _instance;
        ILog _logInstance;

        private FileSystemWatcherWrapper()
        { }

        public FileSystemWatcherWrapper(string pathToMonitor) : this(pathToMonitor, null)
        { }

        public FileSystemWatcherWrapper(string pathToMonitor, ILog logInstance)
        {
            this._instance = new FileSystemWatcher(pathToMonitor);
            _instance.Changed += (s, e) => somethingHappend(s, e);
            _instance.Created += (s, e) => somethingHappend(s, e);
            _instance.Deleted += (s, e) => somethingHappend(s, e);
            _instance.Renamed += (s, e) => somethingHappend(s, e);
            _instance.EnableRaisingEvents = true;

            this._logInstance = logInstance;
        }

        private void somethingHappend(string message)
        {
            this._logInstance?.Log(message);
            this.OnSomethingHappend?.Invoke();

        }

        private void somethingHappend(object sender, FileSystemEventArgs args)
        {
            this.somethingHappend($"Changed file: {args.FullPath} Action: {Enum.GetName(typeof(WatcherChangeTypes), args.ChangeType)}");
        }


        private void somethingHappend(object sender, RenamedEventArgs args)
        {
            this.somethingHappend($"File: {args.OldFullPath} renamed to: {args.FullPath}");
        }

    }

Debug Ausgabe

23.03.2018 14:29:17 :: Changed file: C:\temp\Neues Textdokument.txt Action: Created
23.03.2018 14:29:17 :: Changed file: C:\temp\Neues Textdokument.txt Action: Changed
23.03.2018 14:29:21 :: File: C:\temp\Neues Textdokument.txt renamed to: C:\temp\abc.txt
23.03.2018 14:29:24 :: Changed file: C:\temp\abc.txt Action: Deleted

Vllt. wird es dadurch nun etwas klarer...

 

Edit
wrapper erweitert

Bearbeitet von r4phi
Geschrieben (bearbeitet)

@Eleu: Da du ja meinst, dass ein Hallo-Welt-Programm für dich zu langweilig ist, gebe ich dir mal eine Aufgabe:

Ich gebe dir ein Stück Code vor und du erklärst jedes Schlüsselwort und jeden Begriff:

using System;

namespace ConsoleApp8
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hallo Welt");
        }
    }
}

Also was beutet using und namepace?
Was heißt class? Was ist eine Klasse?
Was ist ein Objekt? Wo liegt der Unterschied zwischen Klasse und Objekt?
Was bedeutet static? Wo ist der Unterschied zwischen static und non-static? 
Was bedeutet void?
Wieso heißt die Methode Main? Kann man sich auch anders benennen?
Was bedeutet "string[] args"?
Was bedeuten die geschweiften Klammern?
Was ist Console?
Was ist WriteLine?
Was ist "Hallo Welt"?

Ich bin mir sicher, dass du die meisten Fragen nicht beantworten kannst und daher bist du bei einem "Hallo Welt"-Programm gut aufgehoben. Bei solchen Programmen geht es nicht nur, um zu sehen, wie "Hallo Welt" auf der Konsole ausgegeben wird, sondern um auch die Basics einer Sprache kennenzulernen und daher ist es wichtig, sich auch mit diesem Programm intensiv auseinanderzusetzen. 

Du behauptest zwar, dass du vor 20 Jahren mit VB6 gearbeitet hast aber ich bezweifel dies, denn offenbar hast du keinerlei Kenntnisse über Objektorientierung, geschweige denn über die Programmierung. 

Ich bin hier auch nun raus, da ich keine Lust habe, jemanden das Programmieren beizubringen, der nicht mal Eigeninitiative zeigt und bei jeder Kleinigkeit sofort ein Post schreibt, anstatt sich selber mal um eine Antwort zu bemühen. Angeblich hast du ja ein Buch. Also dann lese es auch bitte. Ansonsten hast du ja noch Zugang zum Internet und google kennst du ja wohl auch. Auch unsere Fragen, was du da eigentlich vor hast, kannst du auch nicht mal beantworten.

Bearbeitet von Whiz-zarD

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.


Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...