1

Is this the best way to utilize a status message that displays for some time?

private void SetStatus(Color _color, string _msg)
{
    System.Threading.Thread t = new System.Threading.Thread(() =>
    {
        stsStatusMsg.ForeColor = _color;
        stsStatusMsg.Text = _msg;
        System.Threading.Thread.Sleep(2000);
        stsStatusMsg.Text = "";
    });
    t.Start();
}

Example of calling it:

SetStatus(Color.Red, AppMessages["msgALREADYIN"]);

stsStatusMsg (which is a ToolStripStatusLabel) is accessed only by this method during the whole application operation.

The above code actually works. The message is displayed on the control for 2 secs and then goes away...

Adam
  • 15,537
  • 2
  • 42
  • 63
e4rthdog
  • 5,103
  • 4
  • 40
  • 89
  • `stsStatusMsg` is a `StatusStrip`? – Ruel Jul 07 '12 at 09:43
  • @Ruel : it is a ToolStripStatusLabel – e4rthdog Jul 07 '12 at 09:46
  • Haved you considered having another control that is basically a list of all the status messages and the time they are sent; the problem with just flashing the status then removing it is that it can be missed, or, if you wanted to actually see what the message was, you can't really do that. Otherwise, see http://msdn.microsoft.com/en-us/library/ms171728(v=vs.110).aspx - I'm surprised you aren't getting a Cross-Thread access exception. Also see http://stackoverflow.com/questions/1127973/how-do-i-make-cross-threaded-calls-to-a-toolstripstatuslabel – dash Jul 07 '12 at 09:47
  • @dash: See @ruel comment below. The reason i am lucky with the exception is that ToolStripStatusLabel doesnt inherit from a `Control` – e4rthdog Jul 07 '12 at 09:51
  • Ah, the reason why you can do this is indeed in the linked question. – dash Jul 07 '12 at 09:51
  • Also @dash, this is a simple barcode tablet application that makes simple operations.I need the poor forklift guy to see a red big message and then try again... – e4rthdog Jul 07 '12 at 09:53
  • 2
    @e4rthdog No worries, but from a debug/logging point of view, having a place you can go to see all of the status messages pumped to the user (and when) is very useful. I usually have a dockable grid at the bottom of the screen that keeps this info, and displays the last status message in it's title text. I don't think you need a timer though; your solution is effectively an analog of an event - message pumped to the GUI, GUI displays it then wipes it and waits for the next message. – dash Jul 07 '12 at 09:55
  • @dash, yeap it is a working solution , but it is resource consuming for the cpu to create the thread. At least more than the timer. Also i am logging the messages on a table which i send to the supervisor of the drivers in order to react fast...For normal apps i am using similar approach to yours. Thanks. – e4rthdog Jul 07 '12 at 10:01

1 Answers1

5

If this is in WinForms, as I suspect, this is not likely to work. You are only allowed to access the UI controls from the main windows message thread, which can be reached by using Invoke on a Control. Update, while your code does work, this is because the actual object you are manipulating from the thread is not a Control - in general in WinForms, cross thread access is not allowed.

Also, a new thread for each status seems overkill. Yes, the thread is going to be disposed by the GC at some point, but Threads are an expensive resource to create, and your code creates one for each status change. A much better approach is to use the built-in thread pool (where you acquire processing time on a long-lived thread from a pool managed by the framework), or using a Timer, which is designed for running code at specified intervals.

How about changing the text, then use a Timer to hide it again after the desired time ?

Here is a solution using a Timer:

private void SetStatus(Color _color, string _msg)
{
    stsStatusMsg.ForeColor = _color;
    stsStatusMsg.Text = _msg;
    timer.Start();
}

private void StatusTimer_Elapsed(object sender, EventArgs e)
{
    stsStatusMsg.Text = "";
    timer.Stop();
}

The above code assumes that the timer is constructed already, and that it has it's Tick event hooked up to the StatusTimer_Elapsed event. The reason why the System.Windows.Forms.Timer class is well suited for this, is that the timer event is raised on the UI thread, meaning you will not have to worry about cross-thread access to the controls.

Disclaimer: I just thought up the above sample without using a compiler, it might need to be tweaked.

driis
  • 161,458
  • 45
  • 265
  • 341
  • Although i suspect that this is not the best way, it actually works...can you elaborate on invoke? – e4rthdog Jul 07 '12 at 09:42
  • @e4rthdog, is this Windows Forms ? – driis Jul 07 '12 at 09:42
  • yes it is..Sorry for not mentioning, i updated the initial post – e4rthdog Jul 07 '12 at 09:43
  • Why is this an overkill?. The thread is disposed after the work finishes, doesnt it? – e4rthdog Jul 07 '12 at 09:45
  • @driis `ToolStripStatusLabel` doesn't inherit from a `Control`. Which probably makes it Thread-safe – Ruel Jul 07 '12 at 09:49
  • Nice solution, although if i want to exploit the full timer interval, shouldnt you disable the timer on elapsed and enable it every time on SetStatus? – e4rthdog Jul 07 '12 at 09:49
  • @driis; The reason why this works is here: http://stackoverflow.com/questions/1127973/how-do-i-make-cross-threaded-calls-to-a-toolstripstatuslabel?lq=1. – dash Jul 07 '12 at 09:53
  • got it @driis, i am leaving the thread "solution", but i will not use a second timer. I prefer to disable the timer on the elapsed function? What do you say? Set the interval to 2 secs, enable the control on SetStatus and disable it on elapsed. – e4rthdog Jul 07 '12 at 09:56
  • 1
    @e4rthdog, that seems reasonable. However, do be aware that if you generate more than one status message per interval (2 secs), it might be a problem (ie. the user seeing the first message for one sec, then another message for one sec) - I don't know if that will be a problem for your app. If it is; then I will suggest you use an approach where the user can see a list of message instead of just one at a time - as suggested in another comment. – driis Jul 07 '12 at 10:00