Elementów Invoke lub BeginInvoke nie można wywołać w formacie do czasu utworzenia uchwytu okna

0

Witam mam problem z wątkami. Używam do operacji na UserControl i danych BackgroundWorker. Po wykonaniu poniższego kodu:

        private void BackgrounWorkerImport_DoWork(object sender, DoWorkEventArgs e)
        {
            int selected = 0, all = 0;
            Invoke(new Action(() =>
            {
                selected = this.ComboBoxRow.SelectedIndex;
                all = this.ComboBoxRow.Items.Count;
            }));

            for (int i = selected; i < all; i++)
                {
                    this.ImportWorker.ReportProgress(i);
                } 
        }

        private void BackgrounWorkerImport_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            var data = this.ComboBoxRow.SelectedItem.ToString().Split(Convert.ToChar(this.ComboBoxSeparator.SelectedItem.ToString()));

            SqlOperations.ExecProcedure("ImportProcedure", new SqlParameter[]
                {
                      new SqlParameter("@Type", this.DataType),
                      new SqlParameter("@Year", data[0].Split('-')[0]),
                      new SqlParameter("@DataValue", data[1])
                });

            this.ProgressBarImport.PerformStep();
        }

        private void BackgrounWorkerImport_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.LabelTitle.Text = this.LabelTitle.Text + " - Done!";
        }

Powyższy kod zwraca następujący błąd:

screenshot-20201105142514.png

0

Kiedy task startuje? Jeśli w konstruktorze, to najpierw wywołaj InitializeComponent. Jeśli nie masz na to wpływu, to podepnij się pod zdarzenie Load (lub inne, które jest wywoływane po utworzeniu wszystkich parentów) Twojego obiektu i tam startuj task/wątek. W ostateczności (ale to rozwiazanie tak BARDZO słabe, że aż wstydzę się je proponować) w pętli łap wyjątek, poczekaj kilka milisekund i ponów próbę wywołania Invoke, jak się w końcu uda to przerwij pętlę; NIE polecam.

edit: https://stackoverflow.com/questions/49062855/how-to-use-invoke-or-begininvoke-method-to-handle-controls-in-windows-form

0

Na głównej formatce znajduje się FlowPanelLayout w konstruktorze dodaje wszystkie UserControls, które mam. Wykonuje na nich operacje, i gdy wszystkie ogarnę to uruchamiam:

        private void BackgroundWorkerImport_DoWork(object sender, DoWorkEventArgs e)
        {
            Invoke(new Action(() =>
            {
                foreach (Control c in this.FlowLayoutPanelImport.Controls)
                {
                    ((ImportDataRowUserControl)c).ImportWorker.RunWorkerAsync();
                }
            }));
        }

        private void BackgroundWorkerImport_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.Close();
        }

I w tym BackgroundWorker wywołuję te, które rzucają ten wyjątek. Więc wszystkie kontrolki powinny się załadować zanim zdążę wypełnić wszystkie UserControl. W tym kodzie też miałem ten problem, ale udało mi się go rozwiązać przez var h = this.Handle;

Spróbowałem teraz jedno rozwiązanie znalezione w google: https://www.codeproject.com/Questions/549373/InvokeplusorplusBeginInvokepluscannotplusbepluscal
Do swojego kodu dodałem:

if (!this.IsHandleCreated)
     this.CreateControl();

Ale nie pomogło :/

0

Z tego co wiem w procedurze nowego wątku (BackgrounWorkerImport_DoWork) nie powinno się używać bezpośredniego odwołania do kontrolek (np: ComboBoxRow.SelectedIndex). Kontrolki obsługuje wątek główny app, a nie można ich mieszać. Parametry do nowego wątku prześlij poprzez np instancje jakiegoś swojego nowego małego obiektu.

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