C# edycja elementów formy przez wątek dodatkowy

0

Witam, mam problem z zmianą parametrów elementów formy przez wątek pracujący w tle.
Najlepiej podam przykład:

Thread _BackThr = new Thread(delegate() { });
        bool button = false;
        bool backThrOn = false;
        private void button1_Click(object sender, EventArgs e)
        {
            if (!backThrOn)
            {
                backThrOn = true;
                BackThrCreate();
                _BackThr.IsBackground = true;
                _BackThr.Start();
                button1.Text = "Start";
            }
            else
            {
                button = true;
            }
        }
        private void BackThrCreate()
        {
            _BackThr = new Thread(delegate()
            {
                while (true)
                {
                    if (button)
                    {
                        if (button2.Visible)
                        {
                            button2.Visible = false;
                            button2.Text = "Off";
                        }
                        else
                        {
                            button2.Visible = true;
                            button2.Text = "On";
                        }
                        button = false;
                    }
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                }
            });
        }

w powyższym przykładzie po wciśnięciu button1 wątek pracujący w tle ma za zadanie ukryć lub wyświetlić button2 zależnie w jakim stanie jest aktualnie.
Wszystko działa dobrze gdy button2 w chwili startu programu ma właściwość Visible=true, lecz gdy na starcie go ukryję - Visible=false to wszystko przestaje działać jak należy, button2 się w ogóle nie pojawia.

problem udało się rozwiązać poprzez wykonanie metody Invoke na button2
wrzuciłem w pętle while wątku wykonanie tylko funkcji:

private void InvBut2()
        {
            if (button2.InvokeRequired)
            {
                MethodInvoker del = new MethodInvoker(InvBut2);
                button2.Invoke(del);
            }
            else
            {
                if (button)
                {
                    if (button2.Visible)
                    {
                        button2.Visible = false;
                        button2.Text = "Off";
                    }
                    else
                    {
                        button2.Visible = true;
                        button2.Text = "On";
                    }
                    button = false;
                }
            }
        }

Z takim rozwiązaniem niby wszystko działa, ale jest to trochę niewygodny sposób na edycje elementów zawartych w formie.
Gdy wątek dostanie do edycji w przeróżny sposób więcej elementów to będzie to trochę niewygodne do zrealizowania w 1 metodzie, czy choćby kilku.
Tutaj się pojawia pytanie czy da się jakoś to zrobić aby każdy wątek rozpoczęty w np. form1(głównym oknie programu) mógł dokonywać edycji wszystkiego co zawiera form1 (zmienne, elementy takie jak buttony, labele itd) ??
Dodam tylko że nie znam zbyt dobrze języka C# i ogólnie programowaniem zajmuje się głównie dla hobby

1

Żeby dostać się do kontrolek formy z innego wątku, MUSI być Invoke(). Możesz to rozbijać sobie na ile funkcji chcesz, ale musi być przez Invoke.

                MethodInvoker del = new MethodInvoker(InvBut2);
                button2.Invoke(del);

Wystarczy tak:

                button2.Invoke(InvBut2);

Tutaj się pojawia pytanie czy da się jakoś to zrobić aby każdy wątek rozpoczęty w np. form1(głównym oknie programu) mógł dokonywać edycji wszystkiego co zawiera form1 (zmienne, elementy takie jak buttony, labele itd) ??

Nie.

Ale możesz użyć np. lambdy, i napisać coś takiego:

button2.Invoke(() => { button2.Visible = false; });

(nie sprawdzane, może być jakiś problem ze składnią, chodzi o zasadę)

0
Azarien napisał(a):

Wystarczy tak:

                button2.Invoke(InvBut2);

Niestety takie coś nie podchodzi, za to coś takiego tak:

button2.Invoke((MethodInvoker)delegate { InvBut2(); });
Azarien napisał(a):
button2.Invoke(() => { button2.Visible = false; });

(nie sprawdzane, może być jakiś problem ze składnią, chodzi o zasadę)

Tutaj też trochę nie działa ale wystarczy jak w tym u góry zrobić coś takiego:

button2.Invoke((MethodInvoker)delegate { button2.Visible = true; });

W każdym razie dzięki za odpowiedź, trochę mnie nakierowałeś i to mi trochę ułatwiło :)
Jeżeli jednak ktoś by znał lepszy sposób to piszczcie, choćby krótszy o kilka literek :)

0
MrDuelist napisał(a):
Azarien napisał(a):
                button2.Invoke(InvBut2);

Niestety takie coś nie podchodzi, za to coś takiego tak:

button2.Invoke((MethodInvoker)delegate { InvBut2(); });
button2.Invoke((MethodInvoker)InvBut2);

1 użytkowników online, w tym zalogowanych: 0, gości: 1