[C#] this - static

DexXxtrin

Erfahrenes Mitglied
Hallo zusammen

Ich habe ein kleines Problem:
Bei meinem Programm erstelle ich eine Thread, indem das ganze Programm ablauft (Grund: Enthält "endlosschleife")
Nun mit dem Thread können ja nur static typen verwendet werden.
Wenn ich jetzt bei meiner Form z.B ein Label einfüge ist dieses Element ja nicht statisch. Ich habe dann im Form.Designer.cs den Code abgeändert. (this weg und public static anstatt private)
Aber das VisualStudio 2008 macht diesen Vorgan immer Rückgängig, bzw. überschreibt die änderung wieder sobald ich eine Änderung vornehme...

Wie kann ich das lösen, damit ich die Steuerelemente(ComPort, Label, ImageBox,...) auch im Thread benutzen kann?

Vielen Dank

DexXxtrin
 
Hallo,

das klingt für mich als würdest du alles (funktionalität, Threads etc.) in deiner abgeleiteten Form Klasse implementieren.
Ich würde dir raten die Logik und die Oberfläche voneinander zu trennen. (Google -stichwort: "MVC oder MVVM pattern")
In deiner Oberfläche kannst du dann entsprechende Events platzieren und deine Logischen Klassen können sich an diesen Events anmelden. Das ganze per Invoke abarbeiten, damit du auch Threadübergreifend arbeiten kannst. Wenn man sich daran hält hat man am ende die wenigsten Probleme was das aktualisieren der Oberfläche angeht.

Gruß
 
Ich habe das jetzt mal so gelöst. Kann man das so mache, bzw. ist dies eine saubere Variante? (Form wie ich auf das Objekt zugreiffe (Label1))

C#:
    public partial class Main
    {
            ...
            Thread main = new Work().InitializeWork(this);
            main.start();
    }

    public class Work
    {
        private SchlScan myForm;
 
        public Thread InitializeWork(SchlScan myform)
        {
            this.myForm = myform;
            return new Thread(new ThreadStart(this.ReceivedLoop));
        }

        public void ReceivedLoop()
        {
            myForm.Label1.Text = "Test";
        }
     }
 
Hallo,

das funktioniert zwar, allerdings ist es keine saubere Variante, da du eine direkte Abhängigkeit von deiner Form in der Worker Klasse erzeugst. Wenn du es so machen will dann benutze ein Interface der Form um eine saubere Trennung zu gewährleisten.
Ich habe mal ein kleines Beispiel wie ich es lösen würde. Ist sicherlich keine Musterlösung oder ein muss aber vielleicht hilft es etwas. Ich habe das Beispiel von deinem Link etwas abgeändert.

Form Class.
Code:
public partial class MainForm : Form
    {
        MathClass _mathClass = null;

        public MainForm()
        {
            InitializeComponent();

            this._mathClass = new MathClass();
            this._mathClass.NotifyUICall += new UpdateUI(NotifyUICall);
        }

        public void NotifyUICall(int number, int val)
        {
            object o = new object();
            lock(o)
            {
                try
                {
                    if (this.InvokeRequired == false)
                    {
                        this.richTextBox_Output.AppendText(string.Format("thread {0} has done {1} % of its job\n", number, val));
                    }
                    else
                    {
                        this.Invoke(new UpdateUI(NotifyUICall), number, val);
                    }
                }
                catch (System.Exception e)
                {
                    MessageBox.Show(e.Message);
                }                
            }            
        }

        private void button_Run_Click(object sender, EventArgs e)
        {
             _mathClass.Initialize(1);
             _mathClass.Initialize(2);
        }
    }

Math Class:
Code:
class MathClass
    {
        public event UpdateUI NotifyUICall;

        public void Initialize(int number)
        {
            Thread t = new Thread(new ParameterizedThreadStart(this.CalcBackground));
            t.Start(number);
        }

        public void CalcBackground(object number)
        {
            int num = (int)number;
            if(NotifyUICall != null)
            {
                for (int i = 0; i <= 100; i++)
                {
                    NotifyUICall(num, i);
                }
            }            
        }
    }

In den Namespace kommt der delegat, damit der von überall aus erreichbar ist.

Code:
public delegate void UpdateUI(int number, int val);
 
Demfall verstehe ich das doch richtig so:
Ich muss für jede Änderung eine Funktion in der Main-Klasse schreiben, auf die ich dan zugreiffe.
Das heisst ich muss eine Funktion haben, wenn ich den Text eines Labels ändern will, eine Andere wenn ich ein Bild in einer ImageBox laden will...
 
Das kommt immer ganz darauf an was du machen willst. Wenn du den Namen des Bildes in einem Label ausgeben und zeitgleich das Bild anzeigen möchtest, kannst du das auch in einer Methode implementieren. In der NotifyUICall Methode hast du ja kompetten Zugriff auf alle Steuerelemente der Klasse MainForm. Wenn du allerdings Bildanzeige und Labelausgabe von unterschiedlichen Stellen aus setzt dann wäre es ratsam das ganze zu trennen.
 
Zurück