简体   繁体   English

WinForms中的托管线程如何在回调函数中使用“ this->”访问表单的元素(更改值等)

[英]Managed Thread from WinForms how to use “this->” to access elements of the form (change values and etc) in the callback function

Well I have this code in my Managed C++/Cli in Visual Studio 2008, I want to be able to access the windows forms items inside of the callback of the Thread Function, and I can't, it generates an error. 好吧,我在Visual Studio 2008的Managed C ++ / Cli中有这段代码,我希望能够访问Thread Function的回调内部的Windows窗体项,但我不能,它会生成错误。 Is there another way to do that? 还有另一种方法吗? to be able to modify the GUI stuff inside of a method of the WinForms Class by using the Thread function callback ? 能够通过使用Thread函数回调在WinForms类的方法内部修改GUI内容?

This example shows what I want to do. 本示例显示了我要执行的操作。

I need to use a thread because I want to have the other things in the Forms to be accessible, and without using threads everything just freezes until everything is done, and the "Login" function it calls, takes some time because it does HTTP Requests. 我需要使用一个线程,因为我想让Forms中的其他内容可以访问,并且在不使用线程的情况下,一切都冻结了,直到一切完成,并且它调用的“ Login”函数花了一些时间,因为它执行HTTP请求。 and after this HTTP Request I set the values that I got from it in a Form Element. 在此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();
}

Does anybody know how could I do that? 有人知道我该怎么做吗? if you think this can't be done and you want to suggest something something to make the GUI available while doing the process, I'm open for suggestions. 如果您认为无法做到这一点,并且想提出一些建议以使GUI在执行此过程时可用,那么我欢迎您提出建议。

I hope I was being clear enough. 我希望我足够清楚。 Thanks in advance. 提前致谢。

All UI related code should be executed on the UI thread. 所有与UI相关的代码都应在UI线程上执行。 In your case, that means that only the code you denoted with //... should be run on a separate thread. 在您的情况下,这意味着仅用//...表示的代码应在单独的线程上运行。 Extract that long-running code in its own method and pass that method to ThreadStart instead of Login() . 用自己的方法提取该长时间运行的代码,然后将该方法传递给ThreadStart而不是Login() Then you'll need to arrange for a way for the worker thread to notify the UI thread if and when it's complete. 然后,您需要为工作线程安排一种方法,以便在完成时以及在完成时通知UI线程。

Update: 更新:

Here's a crude example of how to modify your code. 这是有关如何修改代码的粗略示例。 I would prefer to extract the long running operation in its own class if it is of sufficient complexity, but I think you get the idea. 如果复杂度足够高,我宁愿将长期运行的操作提取到自己的类中,但是我想您知道了。

The call to BeginInvoke ensures that LongRunningOperationComplete will be executed on the form's UI thread. BeginInvoke的调用可确保LongRunningOperationComplete将在窗体的UI线程上执行。 You can use the same approach to call other methods that update the UI to indicate progress, even while the time-consuming operation is still running. 即使耗时的操作仍在运行,您也可以使用相同的方法来调用更新UI的其他方法以指示进度。 If those methods require more parameters, you can create different delegates with the appropriate signature, and pass those parameters in the call to BeginInvoke . 如果这些方法需要更多参数,则可以创建具有适当签名的其他委托,并将这些参数传递给BeginInvoke的调用。 See here for how to do that. 请参阅此处以了解如何执行此操作。

// 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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM