Zum Inhalt springen

C#: Listbox aus Thread updaten


Guybrush Threepwood

Empfohlene Beiträge

Ich hab ne Form mit ner ListBox drauf und einen Thread der da Einträge hinzufügen soll.

Damit das klappt musste ich mir jetzt extra eine Funktion schreiben die den String für die ListBox als Parameter bekommt und dann einfach nur Listbox.Items.Add() aufruft. Dann musste ich mir ein Delegate auf die Funktion anlegen um die dann im Thread per Invoke aufrufen zu können :rolleyes:

Gibts da nicht nen bequemeren Weg?

Unter C mit der WinAPI hab ich in so fällen einfach immer SendMessage aufgerufen und fertig, aber die Funktion scheint in C# nur für das Compact Framework zu geben...

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 3 Monate später...
  • 1 Jahr später...

Hallo,

bin neu hier und hoffe mir kann jemand helfen. Ich nähere mich auch gerade dem Thema Multithreading, allerdings unter C++. Ich habe jetzt eine CLI-Anwendung erstellt, welche eine Listbox enthält. In dieser möchte ich einfach ein paar Zwischenschritte ausgeben lassen, aber von einem anderen Thread aus. Zudem ist der Thread auch noch in einer anderen Klasse. Ich weiß nicht, ob das eventuell das Problem ist. Jedenfalls habe ich ja schon mitbekommen, dass man da mit diesem delegate arbeiten muss. Und nach tagelangem ausprobieren, habe ich endlich eine Version, bei der der Compiler nicht meckert. Das Problem ist nur, dass sich bei der Listbox gar nichts tut. Könnte mir da eventuell jemand bitte behilflich sein? Was mache ich falsch. Hier mal mein Quellcode (hoffentlich reicht das aus):

Klasse von dem Window-Form:

delegate void AddListItemMethod(String^ str);

AddListItemMethod^ myDelegate;


void AddListItemMethod(String^ str)

{

    lbResults->Items->Add(str);

    lbResults->Update();

}
Aufruf im Thread in einer anderen Klasse
PingTest::Form1^ AddListItemDelegate = gcnew PingTest::Form1;

AddListItemDelegate->AddListItemMethod("huhu");

Ich hoffe, ich habe das Thema nicht komplett missverstanden. Ich bin für jeden Hilfe dankbar.

Viele Grüße

Kati82

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja, das mit dem delegates ist ziemlich heftig, aber einmal verstanden ist das sehr sicher. Nicht wie in anderen Sprachen, da muss man sich 100%ig selbst drum kümmern.

Hab ein Beispiel für Dich aus einem Test von mir:

public delegate void VoidColorStringDelegate(Color color, string text);

		public void Log(Color color, string text)

		{

			if ( text == null || text.Length == 0 )

				return;

			if ( rtbLogs.InvokeRequired )

			{

				rtbLogs.Invoke(new VoidColorStringDelegate(Log), new Object[] {color, text});

				return;

			}

			int iPos = rtbLogs.Text.Length;

			rtbLogs.AppendText(text);

			rtbLogs.Select(iPos, iPos+text.Length);

			rtbLogs.SelectionColor = color;

			rtbLogs.Select(rtbLogs.Text.Length, 0);

			rtbLogs.ScrollToCaret();

		}

		public void LogLine(Color color, string text)

		{

			Log(color, text+"\r\n");

		}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo,

danke erst mal für die schnelle Hilfe. Ich habe aber trotzdem noch ein paar Verständnisprobleme.

  1. Der Thread, von welchen aus ich die Zwischenergebnisse anzeigen möchte, befindet sich ja bei mir in einer anderen Klasse. Das ist in obigen Beispiel ja nicht der Fall. Gibts da noch irgendwas zu beachten?
  2. Ich habe das mit dem InvokeRequired mal ausprobiert. Komischerweise ist diese Bedingung nicht erfüllt. Wenn ich die Hilfe in der MSDN richtig deute, bedeutet das, das kein entsprechendes Handle für dieses Control vorhanden ist. Die Listbox ist doch aber vorhanden, wieso sollte ich doch mal ein Handle erstellen?
  3. Die Zeile mit dem Invoke bekomme ich irgendwie noch nicht richtig hin. Vermutlich liegts an der Syntax von C++/CLI. Aber wenn ich das richtig verstanden habe, müsste ich in meinem Fall im groben so vorgehen:

    public delegate void AddStringDelegate(String^ str);
    
    
    public void AddString(String^ str)
    
    {
    
    	if ( listbox.InvokeRequired )
    
    	{
    
    		listbox->Invoke(new AddStringDelegate (AddString?), .?.);
    
    		return;
    
    	}
    
    	else
    
    	{
    
    		listbox->Items->Add(str);
    
    	}
    
    }


    Ich begreife noch nicht ganz wie ich bei dem Invoke die Parameter angeben soll.

Gibts da eventuell noch ein paar Tipps und Hinweise?

Viele Grüße

Kati82

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wenn ich das so mache kommen folgene Fehlermeldungen:

error C3867: 'PingTest::Form1::AddString': function call missing argument list; use '&PingTest::Form1::AddString' to create a pointer to member

error C3350: 'PingTest::Form1::AddStringDelegate' : a delegate constructor expects 2 argument(s)

Wenn ich mich an den Vorschlag der ersten Fehlermeldung halte und schreibe:

lbResults->Invoke(gcnew AddStringDelegate (&PingTest::Form1::AddString), str);

kommt danach nur noch diese Fehlermeldung:

error C3352: 'void PingTest::Form1::AddString(System::String ^)' : the specified function does not match the delegate type 'void (System::String ^)'

Den String-Parameter bei AddString nochmal zu übergeben bringt nichts.

Läuft denn das bei C++/CLI so komplett anders ab?

Kati82

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wichtig zu beachten sind 3 Dinge:

- ... delegate result name(params); ist nur die Deklaration einer Methodensignatur, damit die Invoke-Methode korrekt aufgerufen werden kann

- man sollte versuchen immer in der Methode selbst zu prüfen, ob ein Invoke notwendig ist, so dass der Zugriff von "Außen" transparent bleibt. Ergo je "näher" am Element, desto besser

- das Control weiss über InvokeRequired() ob ein Recall mittels Invoke(...) notwendig ist. So wie ich die Hilfe verstanden hatte, prüft das die Aufrufende Thread-ID mit der GUI-Thread-ID.

Wie allerdings die Parameterübergabe in C++ genau ausschaut kann ich Dir nicht sagen, mein Beispiel war in C#, aber ich vermute ist ähnlich und in der MSDN beschrieben.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Aus der MSDN für C++:

         array<Object^>^myStringArray = {myString};

         myFormControl1->Invoke( myFormControl1->myDelegate, myStringArray );

Der zweite Parameter von Invoke() ist Object[], d.h. auch wenn die zu invokende Methode nur 1 Parameter hat ist das halt ein Object[0] = str

Bearbeitet von VaNaTiC
Link zu diesem Kommentar
Auf anderen Seiten teilen

Es hat endlich geklappt. Ich habe schon so oft das Beispiel von der MSDN nachzumachen, aber wenn man sich natürlich die falsche Funktion raussucht, wo nur das Delegate übergeben wird und keine Parameter, dann kann es ja nicht klappen. :upps

Ich danke euch nochmal für eure Hilfe.

Viele Grüße

Kati82

Link zu diesem Kommentar
Auf anderen Seiten teilen

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...