Sigmond Gatt Ответов: 2

Потоковая передача в C# winform для отображения ошибки заставки


Привет ребята ,
я пытаюсь показать заставку, но отображается следующая ошибка:

Cross-thread operation not valid: Control 'cmbEnviroment' accessed from a thread other than the thread it was created on



это мой код для нарезания резьбы :

private void LoadInstitutions()
      {
          //Thread.Sleep(3000);

          // OperationClass oc = new OperationClass();
          // oc.loading();
          string selectedValue = cmbEnviroment.SelectedItem.ToString().Trim();
          ConnectionClass connectionClass = new ConnectionClass();
          connectionClass.Connection(selectedValue);

          DataTable table4 = new DataTable();

          string sql4 = "A query to gather data";

          try
          {

              OleDbDataAdapter da4 = new OleDbDataAdapter(sql4, connectionClass.Connection(selectedValue));
              da4.Fill(table4);
              DataRow dr4 = table4.NewRow();
              DataRow dr5 = table4.NewRow();
              dr4["hello1"] = "";
              table4.Rows.InsertAt(dr4, 0);

              cmbInstitution.DataSource = table4;
              cmbInstitution.DisplayMember = "hello1";
              cmbInstitution.ValueMember = "hello1";
          }
          catch (Exception ex)
          {
              MessageBox.Show(ex.ToString());
          }





      }

      private async void cmbEnviroment_SelectedIndexChanged(object sender, EventArgs e)
      {

          //using (new PleaseWait(this.Location))
          //{
              ComboBox senderComboBox = (ComboBox)sender;
              if (senderComboBox.SelectedIndex > 0)
              {
                  LoadingScreen ls = new LoadingScreen();
                  ls.TopMost = true;
                  ls.Show();

                  await Task.Run(() => LoadInstitutions());

                  ls.Close();
               }
          //}

      }


Что я уже пробовал:

я пробовал разные методы, чтобы показать заставку, пока я собираю данные из базы данных, но я застрял .

2 Ответов

Рейтинг:
8

Richard Deeming

Выполните рефакторинг кода, чтобы переместить длительно работающую часть в фоновый поток, и сохраните части, которые обращаются к пользовательскому интерфейсу, в потоке пользовательского интерфейса:

private static DataTable LoadInstitutions(string selectedValue)
{
    ConnectionClass connectionClass = new ConnectionClass();
    const string sql = "A query to gather data";
    
    DataTable result = new DataTable();
    OleDbDataAdapter da = new OleDbDataAdapter(sql, connectionClass.Connection(selectedValue));
    da.Fill(result);
    
    DataRow dr = result.NewRow();
    dr["hello1"] = "";
    result.Rows.InsertAt(dr, 0);
    
    return result;
}

private async Task LoadInstitutions()
{
    try
    {
        string selectedValue = cmbEnviroment.SelectedItem.ToString().Trim();
        DataTable table = await Task.Run(() => LoadInstitutions(selectedValue));
        cmbInstitution.DataSource = table4;
        cmbInstitution.DisplayMember = "hello1";
        cmbInstitution.ValueMember = "hello1";
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

private async void cmbEnviroment_SelectedIndexChanged(object sender, EventArgs e)
{
    ComboBox senderComboBox = (ComboBox)sender;
    if (senderComboBox.SelectedIndex > 0)
    {
        LoadingScreen ls = new LoadingScreen();
        ls.TopMost = true;
        ls.Show();
        try
        {
            await LoadInstitutions();
        }
        finally
        {
            ls.Close();
        }
    }
}


Рейтинг:
2

OriginalGriff

Вы не можете получить доступ к любому элементу управления из любого потока, кроме потока пользовательского интерфейса - когда вы пытаетесь, вы получаете "исключение перекрестного потока", как вы видите.

Два способа исправить это:
1) вызовите элемент управления вместо прямого доступа к нему: Контроль.Вызов Метода (Делегата) (System.Окна.Формы)[^]
2) переместите свой долго работающий код в фоновый поток, используя класс BackgroundWorker, который предназначен для предоставления информации о ходе выполнения потоку пользовательского интерфейса для обновлений.


Sigmond Gatt

привет оригинал , спасибо за ответ на мой вопрос :). маленький вопрос
я сделал это с моим давно работающим кодом :

этот.Invoke((MethodInvoker)делегат ()
{ ...

это работает идеально, но анимированный gif не работает. она просто появится.