[C#] Modyfikacja DataGridView z wątku


(Marcin Obala) #1

Witam

Mam problem z modyfikacją kontrolki DataGridView z wątku. Wcześniej wszystko działało i nagle przestało. Nie przypominam sobie żebym coś zmieniał w kodzie. Modyfikuję tak:

public class ExControl

        {

            public static void AddRowDataGridViewValue(bool val1, string val2, string val3, DataGridView dg)

            {

                if (dg.InvokeRequired)

                {

                    dg.Invoke(new Action(AddRowDataGridViewValue), new object[] { val1, val2, val3, dg });

                }

                else

                {

                    dg.Rows.Add(val1, val2, val3);

                }

            }

            public static void SetDataGridViewValue(int column, int row, string value, DataGridView dg)

            {

                if (dg.InvokeRequired)

                {

                    dg.Invoke(new Action(SetDataGridViewValue), new object[] { column, row, value, dg });

                }

                else

                {

                    dg[column, row].Value = value;

                }


            }

        }

Chodzi o dodawanie wiersza. Program się zawiesza przy Invoke. Widać formę, zazwyczaj jak się zwiesza coś w kodzie to nie widać później formy tylko białe tło. A tutaj ok, widać formę, można zminimalizować, zmaksymalizować i nadal ją widać tylko nie można kliknąć na nią. Wcześniej było wszystko ok tylko nagle przestało działać. Ma ktoś jakiś pomysł? :edit: Znalazłem problem, problemem było

WaitHandle.WaitAll(reset_events);

Kod wygląda tak:

private void GatherDataButton_Click(object sender, EventArgs e)

{

    dataGridView1.Rows.Clear();

    ManualResetEvent GatherDataEvent = new ManualResetEvent(false);

    ThreadInfo GatherData_info = new ThreadInfo(100, GatherDataEvent);

    QueueUserWorkItem(GetPrograms, GatherData_info);

    ManualResetEvent[] reset_events = { GatherDataEvent };

    //WaitHandle.WaitAll(reset_events);

}

matzu może będziesz coś więcej widział bo korzystam z Twojego kodu trochę. Jeśli od komentuję linijkę odnośnie oczekiwania to program zawiesza się przy pierwszym Invoke. Nie ważne ile mogę czekać nie dodaje się ani jeden wiersz do dataGridView.


(Tomek Matz) #2

Czy wywołujesz na obiekcie GatherDataEvent metodę Set()? Metodę tą należy wywołać po to, aby poinformować wątek podstawowy o tym, że wątek dodatkowy zakończył swoje działanie (musisz ją wywołać na samym końcu metody przypisanej do delegata). Inaczej wątek podstawowy będzie wisiał w nieskończoność.

Ogólnie ta linijka WaitHandle.WaitAll([]); jest potrzebna tylko i wyłącznie wtedy, gdy chcesz wstrzymać wykonywanie programu dopóki wybrane przez Ciebie wątki nie zakończą swojego działania. Jeśli nie potrzebujesz wstrzymywać działania programu (bo np. to co wykonywane jest w wybranych przez Ciebie wątkach jest mało istotne), to możesz ją usunąć.

BTW zaktualizowałem przykład z tamtego starego tematu http://forum.dobreprogramy.pl/wielowatkowosc-wielordzeniowosc-t478515.html (wydaje mi się, że jest teraz bardziej czytelny).

I jeszcze jedno ... w tej książce co Ci polecałem jest dobry rozdział o programowaniu wielowątkowym (krótki, ale treściwy). Warto przeczytać. Ciekawa jest także ta seria artykułów (niedawno na nią natrafiłem) http://www.codeproject.com/Articles/152765/Task-Parallel-Library-1-of-n. Również warto się z nią zapoznać.