0

I'm working on a program which requires me to update my windows form GUI from another thread(and not the main thread that created this GUI). I tried using:

rMainGUI->textBox3->Text = "TestDLL Try";
rMainGUI->textBox3->Update();

But the program just got stuck at the first line. And if I remove the first line, it gives me an error during runtime, saying:

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

I want to know if there is some simple, threadsafe, UI updating function that I can use to update the GUI without messing up those threads? Or, if there is some command I can use to pause the current thread, go to main thread, update GUI and then go back to the current thread?

Here are some screenshots: Scr1 Scr2 Scr3

I have an average knowledge about C++, and a little knowledge about threads. Any help would be much appreciated.

Eric
  • 19,525
  • 19
  • 84
  • 147
Bolun Zhang
  • 148
  • 1
  • 10

2 Answers2

1

The answer depends on the Windowin library you are using. Usually they provide a function that takes a function pointer as a parameter that will be ran on the main UI thread.

This is fairly common operation, quick google for "[windows framework] update ui thread" should yield results.

EDIT:

Ok, In winforms you need a delegate. A delegate is the equivalent-ish of a function pointer in regular c++. then you need to invoke it from the UI thread.

I would suggest you look at this question. Basically, you ask your form for InvokeRequired. This asks the form "Will you throw a Cross-thread operation not valid at me if I try to modify you?". If it is true, then you create the delegate and BeginInvoke it from the UI thread. Otherwise it is safe to modify it.

Community
  • 1
  • 1
Eric
  • 19,525
  • 19
  • 84
  • 147
  • Hi Eric, first thank you for your help. Do you mean that if I call some certain function inside the current thread, the function will pause the current thread and let its parameter function run in main thread? – Bolun Zhang Jun 04 '13 at 22:12
  • This should be done asynchronously. You tell the Main thread that you want to run a function, then the main thread will run it when it has time. You seem to be using windows forms with C++/CLI, is this the case? It is impossible to tell for sure how to do it without knowing your framework – Eric Jun 04 '13 at 22:14
  • Yes, this program is C++/CLI Windows Form Application. – Bolun Zhang Jun 04 '13 at 22:23
0

You could try posting a Windows message to the window.

PostMessage((HWND)rMainGUI->textBox3->Handle.ToPointer(), WM_SETTEXT, 0, (LPARAM)L"TestDLL Try");

Not sure if a Windows Forms control responds the same as the older controls, but it's worth a shot.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Hi Mark. First thank you for your help. I tried the command above. Yet I get the following 2 errors: 'type cast' : cannot convert from 'System::IntPtr' to 'HWND'; 'PostMessageW' : cannot convert parameter 4 from 'const wchar_t [12]' to 'LPARAM'; There is no context in which this conversion is possible; – Bolun Zhang Jun 04 '13 at 22:18
  • The compiling is successful. Yet, when the program run to this line, error pops up as "Cross-thread operation not valid: Control 'textBox3' accessed from a thread other than the thread it was created on." – Bolun Zhang Jun 04 '13 at 22:30
  • @zhang835, I give up then if it won't even let you get the window handle. Is there any way you can get that handle from the main thread and pass it in to where you need it? – Mark Ransom Jun 04 '13 at 22:32
  • The rMainGUI is an global static instance, therefore can be used any where in my program. The problem is VC++ seems not allow accessing components from a thread that didn't create them. A possible solution is somehow get back to the main thread and let the main thread update the UI. But sadly I have little idea about how to do that. There are some posts about the similar problem but all in C#. – Bolun Zhang Jun 04 '13 at 22:39