Управляемый поток из WinForms, как использовать «this->» для доступа к элементам формы (изменить значения и т. Д.) В функции обратного вызова - PullRequest
0 голосов
/ 01 апреля 2012

Ну, у меня есть этот код в моем Managed C ++ / Cli в Visual Studio 2008, я хочу иметь возможность доступа к элементам оконных форм внутри обратного вызова функции Thread, и я не могу, она генерирует ошибку.Есть ли другой способ сделать это?чтобы иметь возможность изменять содержимое GUI внутри метода класса WinForms с помощью обратного вызова функции Thread?

В этом примере показано, что я хочу сделать.

Мне нужно использовать потокпотому что я хочу, чтобы другие формы в формах были доступны, и без использования потоков все просто зависает до тех пор, пока все не будет сделано, и вызываемая им функция «Логин» занимает некоторое время, потому что она выполняет HTTP-запросы.и после этого HTTP-запроса я установил значения, полученные из него, в элементе формы.

void Login(){
    this->btn_next->Enabled = false;

    this->login_accounts_facebook->Enabled = false; //This gives an error probably because of accessing "this->"
        if(this->clb_contas->CheckedItems->Count <= 0){
             //...
        }
}

System::Void test_login_Click(System::Object^  sender, System::EventArgs^  e) {
    ThreadStart^ start = gcnew ThreadStart(this, &Login_Test::Login);
    Thread^ t = gcnew Thread(start);
    t->Start();
}

Кто-нибудь знает, как я могу это сделать?если вы думаете, что это невозможно, и хотите что-то предложить, чтобы сделать GUI доступным во время процесса, я открыт для предложений.

Надеюсь, я был достаточно ясен.Заранее спасибо.

1 Ответ

0 голосов
/ 01 апреля 2012

Весь код, связанный с пользовательским интерфейсом, должен выполняться в потоке пользовательского интерфейса.В вашем случае это означает, что только код, обозначенный вами //..., должен выполняться в отдельном потоке.Извлеките этот долгосрочный код в свой собственный метод и передайте этот метод в ThreadStart вместо Login().Затем вам нужно будет определить способ уведомления рабочего потока о потоке пользовательского интерфейса, если и когда он будет завершен.

Обновление:

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

Вызов BeginInvoke гарантирует, что LongRunningOperationComplete будет выполнен напоток пользовательского интерфейса формы.Вы можете использовать тот же подход для вызова других методов, которые обновляют пользовательский интерфейс для индикации прогресса, даже когда длительная операция все еще выполняется.Если этим методам требуется больше параметров, вы можете создать разных делегатов с соответствующей сигнатурой и передать эти параметры в вызове на BeginInvoke.См. здесь , как это сделать.

// Same signature as LongRunningOperationComplete
delegate void MyInvokeDelegate();

void LongRunningOperation() {
  for (int i=0; i < 100; i++) {
    Thread::Sleep(100);
    // The actual work that you're doing
  }

  // Operation complete. Update UI.
  this->BeginInvoke(gcnew MyInvokeDelegate(this, &Login_Test::LongRunningOperationComplete)); 
}

void LongRunningOperationComplete() {
  this->btn_next->Enabled = true;
  this->login_accounts_facebook->Enabled = true;
}

System::Void StartMyLongRunningOperation() {
  ThreadStart^ start = gcnew ThreadStart(this, &Login_Test::LongRunningOperation);
  Thread^ t = gcnew Thread(start);
  t->Start();
}

void Login() {
  this->btn_next->Enabled = false;

  this->login_accounts_facebook->Enabled = false; //This gives an error probably because of accessing "this->"
  if(this->clb_contas->CheckedItems->Count <= 0){
    StartMyLongRunningOperation();
  }
}

System::Void test_login_Click(System::Object^  sender, System::EventArgs^  e) {
  Login();
}
...