-1

Visual Studio C# .NET 5.0 Windows Forms App

Im trying to change a label in my windows form app before performing a ping command but its doesn't work as intendet.

This is my code:

`//some other code
label1.Text = "Pinging specified target... Please wait.";
PingReply reply = ping.Send(target);
label1.Text = "";
//some other code`

The code should change the text of an empty label to "Pinging specified target... Please wait." then run the ping function and then change the label back to blank text.

What happens is, the label only changes after the ping function finished. When i remove the code that changes the label to blank text, the label says "Pinging specified target... Please wait." but only after the ping function ran to completion.

Why does the label change after the ping function when the code is written before the ping function?

Z2008
  • 7
  • 6
  • You're running it on the UI thread. The UI can't updated until after that method finishes running. Run your ping on a different thread then use [`Dispatcher.Invoke`](https://learn.microsoft.com/en-us/dotnet/api/system.windows.threading.dispatcher.invoke?view=windowsdesktop-6.0) to update the UI from that new thread when it's done. – Jesse Oct 28 '22 at 17:07
  • [Here's one of my personal projects displaying how I do it](https://github.com/AppeazeTheCheese/TarkovBundleHelper/blob/main/TarkovBundleHelper/MainWindow.xaml.cs#L156) (don't worry about the top part, just the bottom 3 methods) – Jesse Oct 28 '22 at 17:15
  • @Jesse Wrong UI Platform, this is WinForms -- `label1.Refresh()` before blocking is enough – Jimi Oct 29 '22 at 01:42
  • @Jimi I'm aware, the same process works on both. The `Refresh` method may work in some cases, but you would likely need to call `Application.DoEvents` as well to prevent anything funny from happening. This however is a lot more "hacky" than just running it on a new thread (or in a background worker) and queueing up code to run on the UI thread when you need to using `Dispatcher.Invoke`. – Jesse Oct 30 '22 at 01:58
  • @Jesse *but you would likely need to call Application.DoEvents as well to prevent anything funny from happening*: that's the exact opposite. Calling `Control.Refresh()` cause a call to a *what to do* function ([RedrawWindow](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-redrawwindow)) and a *when to do it* function ([UpdateWindow](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-updatewindow)), which sends the `WM_PAINT` message directly to the Window Procedure of the Control, bypassing the current queue, which means *do it now* [...] – Jimi Oct 30 '22 at 03:33
  • @Jesse [...] which implies that the redraw of the Control is performed before the actions generated by code that comes next are. On the other hand, `Application.DoeEvents` is well known to cause a wide variety of reentrancy problems (though not in this specific case, just redundant) -- `Dispatcher.Invoke` is not directly available in Winforms, where `Invoke()` (synchronous) or `BeginInvoke()` (asynchronous) are used instead. `Dispatcher.Invoke`, though *could* be used (but I don't see a good reason for it), implements a paradigm that is not completely conformant with this platform – Jimi Oct 30 '22 at 03:46

1 Answers1

-2

Actually, it displays the first text but it happens very quickly. To view a transition, you can add some delay by calling Thread.Sleep. However, it is really weird to slow down a task.

`//some other code
label1.Text = "Pinging specified target... Please wait.";
PingReply reply = ping.Send(target);
Thread.Sleep(2000);
label1.Text = "";
//some other code`
jtxkopt
  • 916
  • 1
  • 8
  • 21
  • This is blatantly wrong. All this does is hold up the UI thread longer, making it take more time to update. – Jesse Oct 28 '22 at 17:48
  • Yeah, I already mentioned this. Also, the question doesn't relate to asynchronous programming and has not to do with multi-threading. – jtxkopt Oct 28 '22 at 17:49
  • The question doesn't have to be about multithreading because multithreading is the most common and most elegant solution to do exactly what the OP is trying to do. If they knew that, they probably wouldn't be asking in the first place. The code you posted doesn't do what you say it does. As I mentioned in my comment on the post, this is being ran on the UI thread so the UI is not updated at all until this code finishes. All this code does is make it hang for 2 more seconds. – Jesse Oct 28 '22 at 17:55
  • @Jesse You misunderstood the question. Please, read it more carefully. OP wants to see a transition effect. But it runs very fast and he cannot see a transition. The problem is that. – jtxkopt Oct 28 '22 at 18:00
  • The code they posted doesn't signify that, and neither does the code you posted. Even if that is what they're trying to do, an animation would be performed on the UI thread which this code would be running on. Absolutely nothing UI-related would be able to happen until this code is finished. In either case, adding a `Thread.Sleep` would simply cause the thread to hang longer, and therefore the UI thread has to wait longer to update the UI. The description also doesn't mention anything about a transition anyway so where are you getting that from? – Jesse Oct 28 '22 at 18:08
  • I say again the problem has not to do with a separate thread :) – jtxkopt Oct 28 '22 at 18:14
  • 2
    You're right, the problem has to do with all of this happening on the same thread. Have you tested your code? I can guarantee it doesn't do what you think it does. Can you prove that it answers this question? I don't think you're understanding that the UI doesn't update until the thread is free, unless you add some logic to explicitly tell it to, which you haven't. – Jesse Oct 28 '22 at 18:16
  • Yep, you are rigth. Blocking UI thread prevents the label from being updated since it blocks the message loop. I overlooked that. – jtxkopt Oct 28 '22 at 18:36