Probleme mit Threads
-
Hallo zusammen,
ich habe ein Programm geschrieben dass mir einige Ordner live überwacht und mir Veränderungen in den Ordner mit blinken in der Taskleiste anzeigen soll.
Leider erscheint immer ein Thread-Fehler sobald das Programm eigentlich blinken sollte. Da ich leider noch gar nicht mit Threads gearbeitet habe und sonst auch realtiv unerfahren bin was Programmierung angeht wollte ich fragen ob ihr mir vielleicht weiter helfen könnt bzw. mein Programm so umschreiben könntet, dass es funktioniert ?!
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.Runtime.InteropServices; namespace File_Watcher { public partial class File_Watcher : Form { //Create a Listbox ListBox listbox1 = new ListBox(); //Sets the path for the folder which should be watched string path = @"E:\ePRDATEN\ePRStandesamt"; public File_Watcher() { InitializeComponent(); First(); Run(); } int zähler = 0; //Checks if the folder is empty public bool IsFolderEmpty(string zeile) { DirectoryInfo DirInfo = new DirectoryInfo(zeile); if (DirInfo.GetFiles().Length != 0) { //The folder is empty return true; } else { //The folder is not empty return false; } } private void First() { string Dir = AppDomain.CurrentDomain.BaseDirectory; int fehler = 0; string[] array; string zeile = ""; StreamReader sr = new StreamReader(Dir + @"\pfad.txt"); string zeile_ausschnitt = ""; //Checks if the file pfad.txt exists if (System.IO.File.Exists(Dir + @"\pfad.txt") == true) { array = System.IO.File.ReadAllLines(Dir + @"\pfad.txt"); zeile = sr.ReadLine(); for (int j = 0; j <= array.Length - 1; j++) { //Checks if the folder in the file pfad.txt exits if (System.IO.Directory.Exists(zeile) == false) { zeile_ausschnitt = zeile.Substring(24); listbox1.Items.Add("Der Ordner " + "'" + zeile_ausschnitt + "'" + " existiert nicht."); fehler = fehler + 1; } } if (fehler >= 1) { MessageBox.Show("Einige Ordner in der Datei pfad.txt wurden nicht gefunden, bitte prüfen Sie die Datei auf fehlerhafte Einträge.", "FileWatcher Error"); } else { for (int l = 0; l <= array.Length - 1; l++) { //Checks at the start of File Watcher, if new files are available since last program using if (IsFolderEmpty(zeile) == true) { zeile_ausschnitt = zeile.Substring(24); listbox1.Items.Add("Das Verzeichnis " + "'" + zeile_ausschnitt + "'" + " enthält mind. 1 Datei."); } zeile = sr.ReadLine(); } } } else { MessageBox.Show("Die Datei pfad.txt wurde nicht gefunden, bitte überprüfen Sie ob sich die Datei im gleichen Ordner befindet wie die Datei FileWatcher.exe.", "FileWatcher Error"); } } public void Run() { //Creates a new listbox and set some options listbox1.Size = new System.Drawing.Size(500, 300); listbox1.Location = new System.Drawing.Point(20, 20); listbox1.ScrollAlwaysVisible = true; this.Controls.Add(listbox1); // listbox1.MultiColumn = true; listbox1.SelectionMode = SelectionMode.MultiExtended; //A new instance of the FileWatcher-Class is created FileSystemWatcher watcher = new FileSystemWatcher(); watcher.Path = path; watcher.IncludeSubdirectories = true; watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; watcher.Filter = ""; // Add event handlers. watcher.Changed += new FileSystemEventHandler(OnChanged); watcher.Created += new FileSystemEventHandler(OnChanged); watcher.Deleted += new FileSystemEventHandler(OnChanged); watcher.Renamed += new RenamedEventHandler(OnRenamed); // Begin watching. watcher.EnableRaisingEvents = true; } private delegate void addItemDel(string text); private void addItem(string text) { listbox1.Items.Add(text); } //This method is called if a file has changed private void OnChanged(object source, FileSystemEventArgs e) { if (this.listbox1.InvokeRequired) { addItemDel ad = new addItemDel(addItem); this.Invoke(ad, new object[] { e.ChangeType + " " + "'" + e.FullPath.Substring(26) + "'" }); } else { listbox1.Items.Add(e.ChangeType + " " + "'" + e.FullPath + "'"); } FlashWindow.Start(this); } //This method is called if a file was renamed private void OnRenamed(object source, RenamedEventArgs e) { if (this.listbox1.InvokeRequired) { addItemDel ad = new addItemDel(addItem); this.Invoke(ad, new object[] { e.ChangeType + " " + "'" + e.OldName.Substring(26) + "'" + " -> " + "'" + e.Name.Substring(24) + "'" }); } else { listbox1.Items.Add(e.ChangeType + " " + "'" + e.OldName + "'" + " -> " + "'" + e.Name + "'"); } FlashWindow.Start(this); } //Here the buttons called "Löschen" and "AlleLöschen" are enabled or not enabled private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { if (listbox1.SelectedItems.Count != 0) { Löschen.Enabled = true; AlleLöschen.Enabled = true; } else { Löschen.Enabled = false; AlleLöschen.Enabled = false; } } //This method is called if a user clicks on the "Löschen" button private void Löschen_Click(object sender, EventArgs e) { if (listbox1.Items.Count == 0) { MessageBox.Show("Es ist kein Eintrag vorhanden, den sie löschen könnten", "FileWatcher Error"); } else if (listbox1.SelectedIndex == -1) { MessageBox.Show("Sie haben keinen Eintrag ausgewählt, bitte wählen Sie einen Eintrag aus bevor sie auf Löschen klicken.", "FileWatcher Error"); } else { listbox1.Items.RemoveAt(listbox1.SelectedIndex); } } //This method is called if a user clicks on the "AlleLöschen" button private void AlleLöschen_Click(object sender, EventArgs e) { listbox1.Items.Clear(); listbox1.Update(); } public static class FlashWindow { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool FlashWindowEx(ref FLASHWINFO pwfi); [StructLayout(LayoutKind.Sequential)] private struct FLASHWINFO { public uint cbSize; public IntPtr hwnd; public uint dwFlags; public uint uCount; public uint dwTimeout; } public const uint FLASHW_STOP = 0; public const uint FLASHW_CAPTION = 1; public const uint FLASHW_TRAY = 2; public const uint FLASHW_ALL = 3; public const uint FLASHW_TIMER = 4; public const uint FLASHW_TIMERNOFG = 12; public static bool Flash(System.Windows.Forms.Form form) { if (Win2000OrLater) { FLASHWINFO fi = Create_FLASHWINFO(form.Handle, FLASHW_ALL | FLASHW_TIMERNOFG, uint.MaxValue, 0); return FlashWindowEx(ref fi); } return false; } private static FLASHWINFO Create_FLASHWINFO(IntPtr handle, uint flags, uint count, uint timeout) { FLASHWINFO fi = new FLASHWINFO(); fi.cbSize = Convert.ToUInt32(Marshal.SizeOf(fi)); fi.hwnd = handle; fi.dwFlags = flags; fi.uCount = count; fi.dwTimeout = timeout; return fi; } public static bool Flash(System.Windows.Forms.Form form, uint count) { if (Win2000OrLater) { FLASHWINFO fi = Create_FLASHWINFO(form.Handle, FLASHW_ALL, count, 0); return FlashWindowEx(ref fi); } return false; } public static bool Start(System.Windows.Forms.Form form) { if (Win2000OrLater) { FLASHWINFO fi = Create_FLASHWINFO(form.Handle, FLASHW_ALL, uint.MaxValue, 0); return FlashWindowEx(ref fi); } return false; } public static bool Stop(System.Windows.Forms.Form form) { if (Win2000OrLater) { FLASHWINFO fi = Create_FLASHWINFO(form.Handle, FLASHW_STOP, uint.MaxValue, 0); return FlashWindowEx(ref fi); } return false; } private static bool Win2000OrLater { get { return System.Environment.OSVersion.Version.Major >= 5; } } } } }
Lg SB
-
SilkyB schrieb:
Leider erscheint immer ein Thread-Fehler sobald das Programm eigentlich blinken sollte. Da ich leider noch gar nicht mit Threads gearbeitet habe und sonst auch realtiv unerfahren bin was Programmierung angeht wollte ich fragen ob ihr mir vielleicht weiter helfen könnt bzw. mein Programm so umschreiben könntet, dass es funktioniert ?!
Lg SB
Mutig.
-
Wieso mutig?
-
Weil harter Topac dafür.
-
In den Callback - Funktionen, wie z.B. onChanged (private void OnChanged(object source, FileSystemEventArgs e)) greifst du auf UI - Elemente zu.
Da du dich allerdings in einem asynchron aufgerufen Thread befindest darfst du keine UI - Elemente anlegen oder Sonstiges an der grafischen Oberfläche ändern, dies ist nur dem so genannten STA - Thread, dein Main - Thread, erlaubt.Willst du jetzt trotzdem etwas graphisches ändern, solltest du mit dem Dispatcher in den Main - Thread einbrechen und das dann ausführen.
Wenn du etwas genaueres dazu wissen willst, schau dir mal das Threading - Modell des .NET - Frameworks an
Als Beispiel mal wirklich schnell gemacht, mit Hilfe eines Lambda - Ausdrucks:
private void OnChanged(object source, FileSystemEventArgs e) { if (!this.Dispatcher.CheckAccess()) { this.Dispatcher.BeginInvoke (new Action ( () => { if (this.listbox1.InvokeRequired) { addItemDel ad = new addItemDel(addItem); this.Invoke(ad, new object[] { e.ChangeType + " " + "'" + e.FullPath.Substring(26) + "'" }); } else { listbox1.Items.Add(e.ChangeType + " " + "'" + e.FullPath + "'"); } FlashWindow.Start(this); })); }
-
Fireleger schrieb:
Weil harter Topac dafür.
Topac? Tupac? Oder doch Tobak?