Laden...

Ladeproblem

Erstellt von pkoeppe vor 17 Jahren Letzter Beitrag vor 17 Jahren 2.528 Views
P
pkoeppe Themenstarter:in
319 Beiträge seit 2006
vor 17 Jahren
Ladeproblem

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.

Gelöschter Account
vor 17 Jahren

du kannst nicht einfach von einem thread auf die gui greifen. dazu musst du invoke benutzen und dann geht das (in der forumssuche findest du einige beispiele sowie in der faq)

P
pkoeppe Themenstarter:in
319 Beiträge seit 2006
vor 17 Jahren

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.

Gelöschter Account
vor 17 Jahren

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)

P
pkoeppe Themenstarter:in
319 Beiträge seit 2006
vor 17 Jahren

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.

215 Beiträge seit 2004
vor 17 Jahren

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

P
pkoeppe Themenstarter:in
319 Beiträge seit 2006
vor 17 Jahren
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.