Hallo zusammen,
ich weiß ja nicht, ob sich von Euch jemand mit VRML auskennt, aber ich hoffe (eigentlich geht's ja auch mehr um C#). Folgendes Problem: Um eine VRML Szene darzustellen benutze ich ein Control welches mir in einer DLL eines Drittanbieters zur Verfügung steht. Dieses Control füge ich meinem Form hinzu und lade dann die Szene. Allerdings ist das Laden sehr zeitintensiv (30MB ca. 20sec, und das ist noch eine kleine Szene) und das Form ist in dieser Zeit nicht ansprechbar, was sehr unschön ist. Nun hatte ich überlegt das Laden in einen anderen Thread auszulagern, aber das ist ja auch wieder nicht so toll wegen dem threadübergreifenden Zugriff. Was ich komisch finde ist, dass ich die Visible Eigenschaft des Controls in einem anderen Thread nicht verändern darf, aber die Lade-Methode darf ich aufrufen. Aber das kann es doch auch nicht sein, man kann doch nicht einfach die Methoden eines Controls, welches einem anderen Thread gehört aufrufen, oder (das gibt doch spätestens dann Zoff wenn der Eigentümer-Thread auch die Laden-Methode aufruft oder nicht)!? Hat von Euch jemand eine Idee wie ich das Problem entschärfen kann? Schon mal schönen Dank für Eure Hilfe.
Gruß
Patrick
Wer nicht fragt, bleibt dumm.
Dann findet das Laden der VRML Szene immer noch im UI-Thread statt und dieser ist für mindestens 20 Sekunden geblockt und das möchte ich doch gerade irgendwie unterbinden.
public Form1()
{
InitializeComponent();
Console.WriteLine("UI-Thread ist #{0}", Thread.CurrentThread.ManagedThreadId);
Thread thread = new Thread(new ThreadStart(LoadVrmlInOwnThread));
thread.Start();
}
delegate void VrmlDelegate(String scene);
void LoadVrmlInOwnThread()
{
Console.WriteLine("Lade VRML in Thread #{0}", Thread.CurrentThread.ManagedThreadId);
String scene = "Gesamtlayout.wrl";
this.vrmlControl.BeginInvoke(new VrmlDelegate(LoadVrml), scene);
}
void LoadVrml(String scene)
{
Console.WriteLine("Lade VRML in VRML-Control in Thread #{0}", Thread.CurrentThread.ManagedThreadId);
this.vrmlControl.loadFile(scene);
}
Gruß
Patrick
Wer nicht fragt, bleibt dumm.
Dann findet das Laden der VRML Szene immer noch im UI-Thread statt und dieser ist für mindestens 20 Sekunden geblockt und das möchte ich doch gerade irgendwie unterbinden.
das laden machst du im thread.
von diesem thread aus machst du operationen mit hilfe von invoke auf der gui.
[FAQ] Controls von Thread aktualisieren lassen (Invoke-/TreeView-Beispiel)
Ich habe das Gefühl wir sprechen (schreiben) aneinander vorbei. Ich verwende doch Invoke (bzw. BeginInvoke), was zur Folge hat, dass das eigentliche Laden im UI-Thread stattfindet. Hier nochmal ein an den Link angepasster Code, wo liegt der Hase im Pfeffer???
public Form1()
{
InitializeComponent();
Console.WriteLine("UI-Thread ist #{0}", Thread.CurrentThread.ManagedThreadId);
Thread thread = new Thread(new ThreadStart(LoadVrmlInOwnThread));
thread.Start();
}
delegate void VrmlDelegate(VrmlControl vrmlControl, String scene);
void LoadVrml(VrmlControl vrmlControl, String scene)
{
Console.WriteLine("Lade VRML in VRML-Control in Thread #{0}", Thread.CurrentThread.ManagedThreadId);
vrmlControl.loadFile(scene); // Funktion der DLL
}
void LoadVrmlInOwnThread()
{
Console.WriteLine("Lade VRML in Thread #{0}", Thread.CurrentThread.ManagedThreadId);
String scene = "Gesamtlayout.wrl";
Invoke(new VrmlDelegate(LoadVrml), new Object[] { this.vrmlControl, scene });
}
Gruß
Patrick
Wer nicht fragt, bleibt dumm.
Was Du da gemacht hast ist nur Hin- und Herschubsen des 'Blocking Calls'.
Du blockierst den GUI Thread durch den Invoke Aufruf.
Du musst aber das Laden im (extra) Thread erledigen und die GUI nur über das Ergebnis benachrichtigen.
So sollte es gehen:
public Form1()
{
InitializeComponent();
Console.WriteLine("UI-Thread ist #{0}", Thread.CurrentThread.ManagedThreadId);
Thread thread = new Thread(new ThreadStart(LoadVrmlInOwnThread));
thread.Start();
}
delegate void VoidDelegate();
void Ready()
{
if( InvokeRequired ){
Invoke( new VoidDelegate(Ready),new object[0] );
return;
}
Console.WriteLine("Loading ready");
}
void LoadVrmlInOwnThread()
{
Console.WriteLine("Lade VRML in Thread #{0}", Thread.CurrentThread.ManagedThreadId);
vrmlControl.loadFile("Gesamtlayout.wrl");
Ready();
}
greetz
DaSchroeter
void LoadVrmlInOwnThread() { Console.WriteLine("Lade VRML in Thread #{0}", Thread.CurrentThread.ManagedThreadId); vrmlControl.loadFile("Gesamtlayout.wrl"); Ready(); }
und ich dachte genau das sollte man vermeiden, da es sich ja um einen Zugriff auf Methoden eines Objektes, welches ein anderer Thread besitzt, handelt.
Gruß
Patrick
Wer nicht fragt, bleibt dumm.