-4

I need to change the Label Content. but The code will sleep before execute it. So what's the different I use window execute the code or use control itself? like:

// Use Label execute
Label1.BeginInvoke(new Action(()=>{
         System.Thread.Thread.Sleep(5000);
         Label1.Content = "New Value";
});

// Use Window execute
MainWindow.BeginInvoke(new Action(()=>{
         System.Thread.Thread.Sleep(5000);
         Label1.Content = "New Value";
});

No matter I use Label or Window, it always stuck the UI when the Thread sleep. Why? Why it just don't freeze the label when we execute Label.BeginInvoke() , If Is there no any different, Why Microsoft not remove the Mothod for Control.Begininvoke()

Update1: Sorry for the Sleep(5000), I just let you know there is a method will take a lot time for execute before change the Label Content.

Update2 So If there is no any different, Then no different with Control2.BeginInvoke() and Control3.BeginInvoke() ? Then Why Microsoft just don't keep only the Window.Begininvoke()?

Update3 Why I can change the Control2.Content in Control3.BeginInvoke? If there is no limit Why All has that method? what for?

Update4 Maybe the Update2-3 is dummy qustion, sorry for that, what I mean is : If we can change the label1.content in windows.begininvoke(), why we still need label1.begininvoke()?

qakmak
  • 1,187
  • 7
  • 28
  • 55
  • Why are you doing a `Thread.Sleep(value);` on an invoke? – Nyra Oct 06 '14 at 15:56
  • Aren't you calling the same method, that both instances are inheriting from the same base class? – Ben Robinson Oct 06 '14 at 15:58
  • @alykins, Because That mean there is some method will take alot time, and I don't let the main UI thread stuck in there. – qakmak Oct 06 '14 at 16:01
  • @qakmak - that is poor and bad practice. you should never do a thread.sleep - regardless This causes more problems than you realise and is not a solution to the underlaying problem. – Ahmed ilyas Oct 06 '14 at 16:03
  • @qakmak The sleep will also hang it- and then it will still need to finish the invoke. You should have those methods (that you said need to complete) trigger an event and have the event be subscribed to in the UI, and have the triggered event initiate the invoke. You don't want to do hang-time in your control invoke if all you are doing is updating it- you want it to just update off some other "thing" happening. Don't monitor a process inside a control invoke. – Nyra Oct 06 '14 at 16:08
  • For "Update2" My understanding would be that a Window is a control, but not every control is a window. So you still need invoke for controls that are not a window. And then you have a Window.Invoke for Window objects- I think it's for specificity. – Nyra Oct 06 '14 at 16:10
  • For "Update1" I think you need a little more understanding of Threading, and how the thread queue works and this will become clear. I would suggest start working with threads before moving to working with threads and invoking objects. Get a managed thread program working first, and then move to a graphical display once you understand how it is all playing together. – Nyra Oct 06 '14 at 16:14
  • For "Update3" Can you update your code to reflect this question as it is unclear what you are referring to in this sub-question. You cannot change object2's context with object1's invoke without risking a cross thread invoke exception; you need to invoke object# to affect object#'s values. – Nyra Oct 06 '14 at 16:16
  • For "Update4" because MainWindow.Invoke is just invoking the control MainWindow of the application. It is still a control. The same reason why you would TextBox1.Invoke separate to DropDownList1.Invoke and so on. It is a specifier of the MainWindow property control (ie telling you "what" control to invoke) – Nyra Oct 06 '14 at 16:50
  • Read through [this link](http://stackoverflow.com/questions/14703698/c-invokedelegate) and it may be clearer. Essentially you got some learning to do before this makes a lot of sense. – Nyra Oct 06 '14 at 16:51
  • @alykins, you mean Control.Invoke best than Window.BeginInvoke, because Window.BeginInvoke still execute Control.Invoke, it's just a simple way, but use more cpu than Control.Invoke, because more step? – qakmak Oct 06 '14 at 17:15
  • The MainWindow.Invoke will save you from targeting it through something like `Control c = (Control)Application.MainWindow; c.Invoke(stuff);` to just `MainWindow.Invoke(stuff);` as for performance I am not sure- they may end up being relatively close, but I am not sure. – Nyra Oct 06 '14 at 17:27
  • @alykins, If you code is correct, then you are wrong about "MainWindow will execute all control invoke", I thought you mean Window.Invoke() it will find all Control in Invoke method, then execute it, get more CPU time, but save developer time, but now you just give me a different code. – qakmak Oct 06 '14 at 17:36
  • @qakmak It's fairly unclear what your question is at this time. The answer provided by Tejas and the above comments should be plenty to fix the original question. Can you update your question **and** code to reflect what your current question is? – Nyra Oct 06 '14 at 18:26

1 Answers1

4

From the documentation of Control.BeginInvoke

Executes the specified delegate asynchronously on the thread that the control's underlying handle was created on.

The documentation of Thread.Sleep

Suspends the current thread for the specified amount of time.

Both the Window and the Label were created on the same thread (the UI thread). When you call Thread.Sleep() on that thread (using BeginInvoke) it does exactly what you would expect it to and causes the thread to get suspended (this thread is responsible for listening to windows messages and keeping the UI "responsive" which is why your application freezes)

I noticed that in one of your comments you wrote

@alykins, Because That mean there is some method will take alot time, and I don't let the main UI thread stuck in there.

The solution to this problem is not to call Sleep on the UI thread. You need to hand off the long running task to a separate worker thread and not do it on the UI thread. Consider reading up on the Task Parallel Library for one way to do this.

Answer to your latest update

If we can change the label1.content in windows.begininvoke(), why we still need label1.begininvoke()?

In the unlikely scenario that your Label and Window were created and owned by separate threads (and not the UI thread), you would use Label.BeginInvoke() to update the Label and Window.BeginInvoke() would not work`.

Tejas Sharma
  • 3,280
  • 19
  • 33
  • why you keep saying about sleep ? I already explain it, maybe that code will use UI, maybe that code will change the label other property, but because take some time, then the hole window UI will freezes. you even don't give me the answer what I want – qakmak Oct 06 '14 at 16:38
  • Who said Window.BeginInvoke() would not work? I always use ``this.BeginInvoke(new Action()=>{ Label1.Content = "something";});`` ``this`` mean the Window, and It works fine. – qakmak Oct 13 '14 at 17:39
  • Please read your question and read my answer once again. Thanks. The relevant bits are these: Your question: If we can change the label1.content in windows.begininvoke(), why we still need label1.begininvoke()? My answer: "In the *unlikely* scenario that your Label and Window were created and owned by *separate* threads (and not the UI thread), you would use Label.BeginInvoke() to update the Label and Window.BeginInvoke() would not work`." – Tejas Sharma Oct 13 '14 at 18:23
  • Ok. I'm not see that , So Like what scenario? Can you give me a sample ? – qakmak Oct 13 '14 at 18:28