[c#] Scrollender Text in WinForms

real-insanity

Erfahrenes Mitglied
Hallo zusammen,

mit Hilfe des Internets und ein wenig Googeln habe ich mir einen "Newsticker" für meine WinForm gebaut.
Er klappt auch soweit super jedoch, hängt die komplette Form sobald ich die Methode aufrufe.
Der Ticker aber läuft weiter.

Dies alles erledige ich über einen eigenen Thread.
Da ich auf Steuerelemente der Form zugreife invoke ich diese natürlich.
Ganz durchgeblickt habe ich durch das Threading noch nicht, aber jeder fängt mal klein an.

Hier mein Aufruf:
C#:
new Thread(new ThreadStart(StartScroll)).Start();

Hier die Methode "StartScroll":
C#:
 private void StartScroll()
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder("TEEEEEEEEEEEEEEEEEEEEEEEEEEEEST  ++ ");
            if (lblNewsticker.InvokeRequired)
            { 
                Invoke(new MethodInvoker(StartScroll));
            }
            else
            {
                while (true)
                {

                    char ch = sb[sb.Length - 1];
                    sb.Remove(sb.Length - 1, 1);
                    sb.Insert(0, ch);
                    lblNewsticker.Text = sb.ToString();
                    lblNewsticker.Refresh();
                    System.Threading.Thread.Sleep(100);
                }
            }
        }

Wahrscheinlich ist das für ein geübtes Auge total simpel.
Vielleicht habt Ihr ja eine Idee.

Lieben Gruß
 
Zuletzt bearbeitet:
Ach kein Thema, ich lerne ja noch und lass mich gerne eines anderen belehren.
Kannst du mir kurz erklären, warum meine Lösung schwachsinn war, nur rein zum Verständnis.
Ich hab deine Sachen aus dem Thread übernommen und nun gehts:

C#:
 Thread thread = new Thread(new ThreadStart(delegate() { StartScroll(this); }));
            thread.Start();
C#:
 private void StartScroll(frmMain caller)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder("TEEEEEEEEEEEEEEEEEEEEEEEEEEEEST  ++ ");
            while (true)
            {

                char ch = sb[sb.Length - 1];
                sb.Remove(sb.Length - 1, 1);
                sb.Insert(0, ch);
                
                caller.UpdateText(sb.ToString());
                Thread.Sleep(100);
            }

        }
        public void UpdateText(string text)
        {
            if (this.lblNewsticker.InvokeRequired)
            {
                this.lblNewsticker.BeginInvoke(new MethodInvoker(delegate() { UpdateText(text); }));
            }
            else
            {
                this.lblNewsticker.Text = text;
                lblNewsticker.Refresh();
            }
        }

Vermutlich wird es schwierig, das in einer DLKL auszulagern um es dann leicht wartbar an die Clients bei einem Update zu verteilen oder?
 
Zuletzt bearbeitet:
Lass es mich mal versuchen.
Ich hab das Beispiel as dem anderen Thread mal ein bischen abgeändert so das die ManagedThreadId ausgegeben wird:

Form
C#:
public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();            
        }

        private void button1_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Button1 Click runs on thread : " + Thread.CurrentThread.ManagedThreadId);
            Thread thread = new Thread(new ThreadStart(delegate() { new Vorgang(this); }));
            thread.Start();
        }

        public void UpdateProgressBar(int val)
        {
            if (this.progressBar1.InvokeRequired)
            {
                System.Diagnostics.Debug.WriteLine("UpdateProgressBar before invoke runs on thread " + Thread.CurrentThread.ManagedThreadId);
                this.progressBar1.BeginInvoke(new MethodInvoker(delegate() { UpdateProgressBar(val); }));                
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("UpdateProgressBar after invoke runs on thread " + Thread.CurrentThread.ManagedThreadId);
                this.progressBar1.Value = val;                
            }
        }
    }

Klasse Vorgang
C#:
public class Vorgang
    {
        public Vorgang(Form1 caller) { start(caller); }

        private void start(Form1 caller)
        {
            System.Diagnostics.Debug.WriteLine("Vorgang start runs on thread " + Thread.CurrentThread.ManagedThreadId);
            for (int i = 0; i < 1000; i++)
            {
                caller.UpdateProgressBar(i);
                Thread.Sleep(10);
            }
        }
    }

Wenn du das laufen lässt kommt z.B. sowas dabei raus:
Code:
Button1 Click runs on thread : 8
Vorgang start runs on thread 9
UpdateProgressBar before invoke runs on thread 9
UpdateProgressBar after invoke runs on thread 8
UpdateProgressBar before invoke runs on thread 9
UpdateProgressBar after invoke runs on thread 8
...

Das bedeutet jetzt für deinen Fall das du dich an folgender Stelle wieder im Thread deiner Form befindest. ( Deswegen invoken wir ja überhaupt )
C#:
else
            {
                while (true)
                {
 
                    char ch = sb[sb.Length - 1];
                    sb.Remove(sb.Length - 1, 1);
                    sb.Insert(0, ch);
                    lblNewsticker.Text = sb.ToString();
                    lblNewsticker.Refresh();
                    System.Threading.Thread.Sleep(100);
                }
            }

Demnach schickst du auch den Thread der Form in den Sleep.
Und überhaupt hättest du dir das ganze auslagern in einen anderen Thread ( so wie du es umgesetzt hast ) demnach auch sparen können.
 
Ah okay, nun ist es was klarer.
Spricht ich hab das in einen Thread geschickt und dennoch die Form durch das Sleep (weil ich ja invoke und wieder im eigentlichen Form-Thread bin) komplett lahmgelegt. Ok, verstanden. Super, dank dir!
 
Zurück