Kompletter Error:
Message: Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.
Der Fehler tritt genau hier auf:
richTextBox1.Text += "ChangeT
ype :: " + e.ChangeType.ToString() + "\nFullPath ::" + e.FullPath.ToString() + "\n\n";
Wenn ich die Zeile einfach in eine string Variable packe gehts, ich möchte es aber direkt in die Textbox parsen. Weis jemand Rat? Danke!
Ich hab das definiert:
private System.Windows.Forms.RichTextBox richTextBox1;
Und diesen Code:
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace FolderWatcher_
{
public partial class Form1 : Form
{
private FileSystemWatcher myWatcher;
private Button btnAddFile, btnAddDir, btnDelDir, btnDelFile, btnExit;
string DirPath;
public Form1(string myPath)
{
DirPath = myPath;
InitializeComponent();
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
myWatcher = new FileSystemWatcher(DirPath);
myWatcher.EnableRaisingEvents = true;
myWatcher.IncludeSubdirectories = true;
myWatcher.Created += new FileSystemEventHandler(myWatcher_Created);
myWatcher.Changed += new FileSystemEventHandler(myWatcher_Changed);
myWatcher.Deleted += new FileSystemEventHandler(myWatcher_Deleted);
myWatcher.Renamed += new RenamedEventHandler(myWatcher_Renamed);
}
public static void Main()
{
myProperties myprop = new myProperties();
myprop.ShowDialog();
Application.Run(new Form1(myprop.myPath));
}
//Creating New File
protected void btnAddFile_Click(object sender, EventArgs e)
{
}
// Created Event
protected void myWatcher_Created(object sender, FileSystemEventArgs e)
{
richTextBox1.Text += "ChangeType :: " + e.ChangeType.ToString() + "\nFullPath ::" + e.FullPath.ToString() + "\n\n";
}
//Changed Event
protected void myWatcher_Changed(object sender, FileSystemEventArgs e)
{
richTextBox1.Text += "ChangeType :: " + e.ChangeType.ToString() + "\nFullPath ::" + e.FullPath.ToString() + "\n\n";
}
//Deleted Event
protected void myWatcher_Deleted(object sender, FileSystemEventArgs e)
{
richTextBox1.Text += "ChangeType :: " + e.ChangeType.ToString() + "\nFullPath ::" + e.FullPath.ToString() + "\n\n";
}
//Renamed Event
protected void myWatcher_Renamed(object sender, RenamedEventArgs e)
{
richTextBox1.Text += "ChangeType :: " + e.ChangeType.ToString() + "\nFullPath ::" + e.FullPath.ToString() + "\nOld FileName :: " + e.OldName.ToString() + "\n\n";
}
}
}
Hi,
von einem anderen Thread kann man nicht auf die User Controls zugreifen, dafür musst du
Control.Invoke oder Control.BeginInvoke aufrufen.
Statt der Zuweisung:
richTextBox1.Text += "...";
solltest du nen Delegate erstellen und prüfen ob ein Invoke erforderlich ist.
z.B. so:
private delegate void AppendTextHandler(string s);
private void AppendText(string s)
{
if( richTextBox1.InvokeRequired )
richTextBox1.Invoke(new AppendTextHandler(AppendText), new object[]{s});
else
richTextBox1.Text += s;
}
Ok danke so hats geklappt:
protected void myWatcher_Created(object sender, FileSystemEventArgs e)
{
//FileStream file = new FileStream("change.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
//StreamWriter sw = new StreamWriter(file);
//sw.Write("ChangeType :: " + e.ChangeType.ToString() + "\nFullPath ::" + e.FullPath.ToString() + "\n\n");
//sw.Close();
string s = "ChangeType :: " + e.ChangeType.ToString() + "\nFullPath ::" + e.FullPath.ToString() + "\n\n";
AppendText(s);
}
private delegate void AppendTextHandler(string s);
private void AppendText(string s)
{
if( richTextBox1.InvokeRequired )
richTextBox1.Invoke(new AppendTextHandler(AppendText), new object[]{s});
else
richTextBox1.Text += s;
}
Seit dem Umstieg auf .NET 2 kommt bei mir auch immer dieser Fehler
Cross-thread operation not valid:
Ich will aber nicht meinen ganzen Quellcode umschreiben. Gibt es keine schnellere Möglichkeit außer invoke() und delegate ?
Hallo alf468,
das die Exception bei 1.1 nicht kommt, ist ein Bug von 1.1. Stattdessen können bei 1.1 lustige Effekte auftreten. Es kann sein, dass diese Effekte nur unter bestimmten Bedingungen auftreten (Racing Conditions). Dein Code ist also fehlerhaft (auch wenn du keine Exception bekommst und auch wenn die Effekte nicht auftreten). Die einige Lösung ist den Code umzuschreiben. Zum Trost: Invoke ist simpel.
herbivore
Hallo,
Nach der Umstellung auf .Net 2.0 kam bei mir genau die gleiche Fehlermeldung. Also habe ich auch die Delegates und Invokes eingebaut. Mein Problem ist jetzt, dass die Invokes erst ausgeführt werden,w enn der Thread beendet ist. Das hat zur Folge, dass alle Nachrichten die ich in einem Fenster ausgeben wollte, erst ganz am Ende angezeigt bekomme. Damit fehlen dem Nutzer genau die Rückmeldungen, um die es mir dabei ging. Hat jemand ne Idee, was ich daran ändern muss.
Natsukawa
Kannst Du mal ein Code-Beispiel posten ?
Oder hast Du das vielleicht blockierend programmiert ?
D.h.: wartet Dein "Haupt"-Thread bis der andere Thread, aus dem die Nachrichten kommen, tot ist? Dann wärs klar, warum.
Hallo,
Ja der Hauptthread muss auf die anderen Threads warten. Das liegt daran, dass zwischendurch einige Aufgaben parallel in den Threads laufen, und danach der Hauptthread etwas auswerten muss.
Beispiel posten ist etwas schwierig, es verteilt sich auf viele Klassen und so.
Wieos muss den der Hauptthread beendet sein, damit die Nachrichten zur Control durchgereicht werden?
Natsukawa
hi!
dein Problem ist folgendes: Wenn ei Thread auf einen anderen wartet, dann ist der wartende Thread blockiert. Als Lösung würde sich anbieten, erst einen "zwischenthread" zu starten, welcher deinen eigentlichen Arbeitsthread aufruft und auf ihn wartet. Per Events müssen die Daten aus deinem eigentlichen Arbeitsthread in den GUI-Thread gelangen. Insgesamt wären das bei der Lösung also 3 Threads. (GUI + Zwischenthread + Arbeitsthread)
der Marcel
:] 😄Der größte Fehler eines modernen Computers sitzt meist davor 😁 :]
Nee, der muss nicht beendet sein. Geht ja auch nicht. Er darf nicht blockiert werden. Also ich mein jetzt der Thread in dem die GUI läuft, der darf nicht blockiert werden, sonst passiert da garnichts. Der hängt dann an der Stelle, wo er drauf wartet, daß die anderen Thread zurückkommen. Und erst wenn DIE ihre Arbeit beendet haben, dann läuft er weiter.
Um das zu verhindern, musst Du das mit Threads also so programmieren, daß sie den GUI-Thread nciht blockieren. Das reicht ja, wenn die sowas wie ein "ich bin fertig"-Event schicken. Oder per BeginInvoke und Callback ihr Ergebnis abliefern. Und wenn alle Threads das gemacht haben, wird ausgewertet.
Haha, zwei Dumme, ein Gedanke. Warst schneller, Marcel 😁
Hallo,
Danke, dass mit dem Bin-Fertig-Event werd ich gleich mal probieren.
Natsukawa
Hallo ich habe eine kleines Problem.Ich will ein Item in einer Listbox einfügen.
Dabei kommt folgender Fehler:
System.InvalidOperationException: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
Die Listbox ist static hat das Problem damit was zu tun ?
Das ist das erste Mal das ich damit Probleme habe 🙁
Hallo alf468,
es ist so wie die Meldung sagt.
Der Handle eines Controls wird erst bei Show oder explizit durch CreateHandle/Handle erzeugt.
herbivore