Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Timer isn't ticking!
Message
De
07/11/2008 12:43:42
Mark Hall
Independent Developer & Voip Specialist
Keston, Kent, Royaume Uni
 
 
À
07/11/2008 11:12:26
Timothy Bryan
Sharpline Consultants
Conroe, Texas, États-Unis
Information générale
Forum:
ASP.NET
Catégorie:
Formulaires
Versions des environnements
Environment:
C# 3.0
OS:
Windows XP SP2
Network:
Windows XP
Database:
MS SQL Server
Divers
Thread ID:
01360368
Message ID:
01360556
Vues:
7
>>>Hi Mark,
>>>
>>>>Hi,
>>>>
>>>>I'm a VFP guy, just getting a handle on C#.
>>>>
>>>>I have a Winform, containing some custom controls (assemblies of buttons, labels and text boxes).
>>>>
>>>>I have an event being created (when a telephone call is received) and at that time I change some text on one of the custom controls.
>>>>
>>>>So far, so good - all works well.
>>>>
>>>>Now, when the phone rings, I want the line status text on my custom control to flash 'Ringing' rather than just display the word. So, I have added a timer that runs every second (when enabled) and changes the ForeColor of the status label to give a flashing effect.
>>>>
>>>>Except - it doesn't flash.
>>>>
>>>>I think it has something to do with threads. The fact that the timer on the custom control is enabled from an event handler seems to inhibit it's function somehow.
>>>>
>>>>If I set the timer to enabled at design time, then the text flashes from the start, proving that my flash code is OK.
>>>>
>>>>Any suggestions greatfully received.
>>>
>>>If you are using VS2005 or VS2008 you should get a cross thread exception if that was the case and I understand you correctly. Try using Invoke on your method like this.
>>>
>>>/// <summary>
>>>/// MyOtherThread Event Handler
>>>/// </summary>
>>>private void myOtherThread_EventFired(object o, SomeEventArgs e)
>>>{ this.Invoke(new SomeDelegate(OnMyEvent), new object[] { o, e }); }
>>>private void OnMyEvent(object sender, SomeEventArgs e)
>>>{
>>>     // Change your control properties here
>>>}
>>>
>>>
>>>Otherwise, maybe you could post some of your code showing how you are trying to enable the timer and the timer method that is changing your text value. We could probably get a better idea of what is happening. Also if the label you are trying to change is inside a user control then you will have to handle it a bit differently. Try posting some code.
>>>Tim
>>
>>Hi Tim,
>>
>>It's VS 2008. You are correct about the cross thread exception. I did encounter this when I wrote the code to change the status text on my control via the event handler. I cheated and added
>>
Control.CheckForIllegalCrossThreadCalls = false;
>>to the start of my form.
>
>I did that a few times when I upgraded from VS2003 to VS2005 as it only was a warning in VS2003. In VS2005 MS changed it to generate an exception. Now I only use the Invoke for safety.
>
>
>>
>>Looks like I'm going to have to bite the bullet and do it the right way. I had just worked out the whole event/delegate bit when I first wrote this code so I had a headache at the time.
>>
>>The label (and other stuff) that needs to be changed IS inside a custom control (which is added to the form dynamically at run-time) - how much different does this make it from your proposed solution above?
>>
>>Thanks.
>
>Have you set a breakpoint in the timer_tick handler to verify if the event is firing and your textbox just isn't getting updated? The problem with your textbox being inside a user control is how are you accessing it? Can you show abreiviated code on how you are trying to make your text blink? My guess is if the textbox is in a user control you will need to have property of the user control that changes the textbox itself. Then your timer event can set the property of the user control which sets the textbox.
>Tim

Hi,

I did put a debug.writeln("tick fired") but it was never displayed in the debug output window, so the tick code isn't executed.

I know that the code that enables the timer is running, as it also changes the text of a label, and changes the background color of the custom control.

OK, here's some of the code. It's my first ever C# application, so may be a little disorganised.

First, the event handler that gets called whenever the state of a phone line changes.
clsLine manages the interface to the actual phone system, and raises events when calls come and go.
The code must allow for a variable number of physical phone lines, so at application startup, the number of lines
is detected and a corresponding number of clsLine and CtlPhoneLine1 (on-screen representation) objects
are created.
When the state of a phone line changes, this code then loops through the controls on the form to find the
correct matching on-screen representation of the appropriate phone line (by matching Index property).
Do let me know if there is a better way of doing this.
This code is a method on the main form
      private void OnLineStatChg(object sender, EventArgs e)
        {
            //This event handler fires whenever the status of a clsLine (phone line) changes
            //Find the corresponding screen line representation, then call the refresh code, below.
  
            //I added the following line for debugging and it does display the text
            if (this.InvokeRequired == true) Debug.WriteLine("Invoke Required");

            clsLine theline = (clsLine) sender;
            foreach (CtlPhoneLine1 obj in this.Controls)
            {
                if (obj is CtlPhoneLine1)
                {
                    if (obj.Index == theline.Index)
                    {
                        this.RefreshLine(theline, obj);
                        goto FoundIt;
                    }
                }
            }
            FoundIt:
            return;
        }
Once the correct CtlPhoneLine1 is found, another form method is called to make the actual changes.
       private void RefreshLine( clsLine LineObj, CtlPhoneLine1 LineCtl)
        {
            //This code sets the properties of the appropriate ctlPhoneLine control
            //When a call enters or leaves the queue.
            LineCtl.CallerId = LineObj.Callerid;
            LineCtl.CallerIdName = LineObj.Callername;
            switch (LineObj.State)
            {
                case LineState.LineClear:
                    LineCtl.Status = "Clear";
                    break;
                case LineState.LineRinging:
                    LineCtl.Status = "Ringing";
                    break;
                case LineState.lineHungup:
                    LineCtl.Status = "Hungup";
                    break;
            }
        }
CtlPhoneLine1 is my custom control.
In the Set method of the Status property of CtlPhoneLine1, the code that adjusts the appearance of various parts of the control runs.
        public string Status
        {
            get
            {
                return this._status;
            }
            set
            {
                this._status = value;
                //Call a method to re-set control appearance based on state
                this.SetAppearance(this._status);
            }
        }
And finally, the CtlPhoneLine1 SetAppearance method makes the changes.
       private void SetAppearance(string state)
        {
            switch (state)
            {
                case "Ringing":
                    tmrFlash.Start();
                    lblStatus.Text = state;
                    this.BackColor = Color.Red;
                    break;
                case "Hungup":
                    tmrFlash.Stop();
                    lblStatus.Text = "Available";
                    this.BackColor = Color.Yellow;
                    break;
                case "Clear":
                    tmrFlash.Stop();
                    lblStatus.Text = "Available";
                    this.BackColor = Color.Yellow;
                    break;
            }
        }
On my form, I was able to reference an Enum that I create for LineState, but notice that I had to then change that to a string when passing through to the CtlPhoneLine1 control. This is because I developed the control as a seperate project (added as part of the whole solution), but I can't seem to access classes and types created as part of the main solution from within CtlPhoneLine1. I have tried adding a using.. of r the main project namespace but it didn't work - any suggestions here too would be useful.

Thanks,
Regards
Mark

Microsoft VFP MCP
Menulib - OO Menus for VFP www.hidb.com/menulib
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform