Click here to Skip to main content
15,889,527 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,
I am developing an application using Asterisk.NET Library, and I am subscribed to an event "NewStateEvent" to get the incoming calls from the server..
Now, I noticed that The NewState Event doesnt occur again until the last NewStateEvent is finished. I assume that its working on a single thread; that will start another thread only when the last one is finished... (I had to Invoke form to use form controls in the event)...
Is there any idea to allow mumltiple instances of a thread within my NewState Event ??

This is the code structure...
C#
public void New_State_Event(object sender, Asterisk.NET.Manager.Event.NewStateEvent e)
       {

               if (e.ChannelStateDesc != null && e.Attributes.ContainsKey("connectedlinenum"))
               {
                   switch (e.ChannelStateDesc.ToLower())
                   {
                       case "ringing":
                           if (ApplicationVariables.CurrentExtensions.ContainsValue(e.CallerIdNum))
                           {

                                  this.Invoke(new MethodInvoker(delegate()
                                       {
                                           Label1.Text = "Ringing";
                                       }));
                                   

                           }

                           break;
                       case "up":
                           if (CallingInfo.UniqueId == e.UniqueId)
                           {
                               this.Invoke(new MethodInvoker(delegate()
                                {
                                         Label1.Text = "Line is up";
                                }));
                           }
                           break;

                   }
               }


       }


and Actual code is this ....


C#
public void New_State_Event(object sender, Asterisk.NET.Manager.Event.NewStateEvent e)
    {

        try
        {

            if (e.ChannelStateDesc != null && e.Attributes.ContainsKey("connectedlinenum"))
            {
                switch (e.ChannelStateDesc.ToLower())
                {
                    case "ringing":
                        if (ApplicationVariables.CurrentExtensions.ContainsValue(e.CallerIdNum))
                        {
                            //  Creating thread for Timer to work
                            //System.Threading.Thread timerthread = new System.Threading.Thread(delegate()
                            //{
                                try
                                {

                                    this.Invoke(new MethodInvoker(delegate()
                                    {
                                        if (this.Opacity != 98) this.Opacity = 98;
                                        if (exw != null && !exw.IsDisposed)
                                        {
                                            if (exw.calo != null && !exw.calo.IsDisposed)
                                                exw.calo.Opacity = 0;
                                            if (exw.cf != null && !exw.cf.IsDisposed)
                                                exw.cf.Opacity = 0;
                                            exw.Opacity = 0;
                                        }

                                        SetPopupLocation();
                                        button8.Visible = true;
                                        button1.Visible = true;
                                        button2.Visible = true;
                                        button4.Visible = false;
                                        linkLabel1.Visible = false;
                                        pictureBox1.Enabled = true;
                                        if (!this.Visible)
                                        {
                                            this.Show();
                                            this.TopMost = true;
                                        }
                                        if (exw != null && exw.Visible)
                                        {
                                            if (LOADSTYLE == NativeClasses.AW_VER_POSITIVE)
                                            {
                                                Taskbar tt = new Taskbar();

                                                exw.Top = 121 + tt.Size.Height;
                                            }
                                            else
                                            {
                                                Rectangle rr = new Rectangle();
                                                rr = Screen.GetWorkingArea(rr);
                                                exw.Top = (rr.Height) - (exw.Height + 121);
                                            }
                                        }

                                        //string callingperson = "", callingnumber = "";
                                        label2.Text = String.Format(Language.incoming_call_for_the_extension, e.CallerIdNum);


                                        if (e.Attributes.ContainsKey("connectedlinename") && e.Attributes.ContainsKey("connectedlinenum"))
                                        {
                                            CallingInfo.linenum = e.Attributes.ContainsKey("connectedlinenum") ? e.Attributes["connectedlinenum"] : " Unknown ";
                                            label1.Text = String.Format(Language.num_is_calling, CallingInfo.linenum, CallingInfo.linenum, "", "");
                                            Application.DoEvents();
                                            if (e.Attributes["connectedlinename"] != "" && e.Attributes["connectedlinename"] != e.Attributes["connectedlinenum"])
                                            {
                                                CallingInfo.linename = e.Attributes["connectedlinename"];
                                                //CallingInfo.linenum = e.Attributes.ContainsKey("connectedlinenum") ? e.Attributes["connectedlinenum"] : " Unknown "; //+ " ] is Calling...";
                                            }
                                            else
                                            {
                                                Type officeType = Type.GetTypeFromProgID("Outlook.Application");
                                                if (officeType == null || ApplicationVariables.look_for_contact_in_outlook == false)
                                                {
                                                    if (ApplicationVariables.use_local_phone_book == true)
                                                        CallingInfo.linename = GetPhoneContact(e.Attributes["connectedlinenum"]);
                                                    else
                                                        CallingInfo.linename = "Unknown";
                                                }
                                                else
                                                {
                                                    CallingInfo.linename = OutlookData.SearchContact(OutlookData.OutlookContactList, e.Attributes["connectedlinenum"]);
                                                    if (CallingInfo.linename == "Unknown")
                                                        CallingInfo.linename = GetPhoneContact(e.Attributes["connectedlinenum"]);
                                                }
                                                //CallingInfo.linenum = e.Attributes.ContainsKey("connectedlinenum") ? e.Attributes["connectedlinenum"] : " Unknown ";

                                            }
                                        }

                                        label1.Text = String.Format(Language.num_is_calling, CallingInfo.linename, CallingInfo.linenum,"","");
                                        CallingInfo.channel = e.Channel;
                                        CallingInfo.CalledExten = e.CallerIdNum;
                                        CallingInfo.UniqueId = e.UniqueId;
                                        CallingInfo.CallTaken = false;
                                        Status_counter = 0;
                                        timer_autohangup.Enabled = true;
                                        CallerInfo.SetCallInfo(CallingInfo.linename, CallingInfo.linenum, e.CallerIdNum, 0, DateTime.Now, e.UniqueId);
                                        SendStatustoXMPP("Phone  Ringing...");
                                    }));
                                }
                                catch (Exception ex)
                                {
                                    DebugLogger.LogRecord(ex.Message + " [ Function: " + System.Reflection.MethodBase.GetCurrentMethod().Name + ", Thread, Class: ContactList ]");
                                }
                            //});
                            //timerthread.Start();
                        }

                        break;
                    case "up":
                        if (CallingInfo.UniqueId == e.UniqueId)
                        {
                            this.Invoke(new MethodInvoker(delegate()
                             {
                                 CallingInfo.CallTaken = true;
                                 button8.Visible = false;
                                  button1.Visible = true ;
                                 button2.Visible = false;
                                 button4.Visible = true;
                                 linkLabel1.Visible = false;
                                 pictureBox1.Enabled = false ;
                                 timer_autohangup.Enabled = false;
                                 //string callingperson = "", callingnumber = "";
                                 label2.Text = String.Format(Language.talking, e.CallerIdNum);
                                 //if (e.Attributes.ContainsKey("connectedlinename") && e.Attributes.ContainsKey("connectedlinenum"))
                                 //    if (e.Attributes["connectedlinename"] != "" && e.Attributes["connectedlinename"] != e.Attributes["connectedlinenum"])
                                 //    {
                                 //        CallingInfo.linename = e.Attributes["connectedlinename"];
                                 //        CallingInfo.linenum = e.Attributes.ContainsKey("connectedlinenum") ? e.Attributes["connectedlinenum"] : " Unknown "; //+ " ] is Calling...";
                                 //    }
                                 //    else
                                 //    {
                                 //        Type officeType = Type.GetTypeFromProgID("Outlook.Application");
                                 //        if (officeType == null)
                                 //        {
                                 //            CallingInfo.linename = GetPhoneContact(e.Attributes["connectedlinenum"]);
                                 //        }
                                 //        else
                                 //        {
                                 //            CallingInfo.linename = OutlookData.SearchContact(OutlookData.OutlookContactList, e.Attributes["connectedlinenum"]);
                                 //            if (CallingInfo.linename == "Unknown")
                                 //                CallingInfo.linename = GetPhoneContact(e.Attributes["connectedlinenum"]);
                                 //        }

                                 //        CallingInfo.linenum = e.Attributes.ContainsKey("connectedlinenum") ? e.Attributes["connectedlinenum"] : " Unknown "; //
                                 //    }
                                 label1.Text = string.Format(Language.talking_to,   CallingInfo.linename , CallingInfo.linenum );
                                 CallerInfo.SetCallInfo(CallingInfo.linename, CallingInfo.linenum, e.CallerIdNum, 1, DateTime.Now, e.UniqueId);
                                 SendStatustoXMPP("Calling over Asterisk...");
                             }));
                        }
                        break;

                }
            }

        }
        catch (Exception ex)
        {
            DebugLogger.LogRecord(ex.Message + " [ Function: " + System.Reflection.MethodBase.GetCurrentMethod().Name + " Class: " + this.GetType().Name + " ]");
        }


    }



Please Help...
Posted
Updated 21-Oct-13 1:43am
v5
Comments
Andreas Gieriet 20-Oct-13 19:07pm    
Why would the event start another thread? Your callback handler will always be called on the same thread where the event is triggered. *You* have to take care if your handler shall delegate the task to another thread or not.
But in your code above, delegating to another thread is overengineering to me, since no action looks time consuming except mayby your ContainsValue method calls?
Cheers
Andi
Sergey Alexandrovich Kryukov 20-Oct-13 21:12pm    
You are absolutely right. As to "over-engineering", the problem is not just over-engineering: such delegation to different threads would be totally useless, because ultimately the delegation will come to the same UI thread, due to the use of Control.Invoke. Please see my Solution 2 and my comment to Solution 1.
—SA

I hope you rightfully uses Control.Invoke, because your network-related event should really be invoked from some non-UI thread. At least, this is something you should really have done. And, by the same reason, checking Control.InvokeRequired would be redundant. This is if the invocation of the event really happens in some non-UI thread.

It looks like your only problem is hoping for parallel handling of the event. You should understand what Control.Invoke does. It delegates execution to the UI thread. If you delegate some method to the UI thread as a result of some event invocation, naturally, the calls will be serialized on the UI thread, so, there is nothing which would make this handling parallel, more important, such parallelism would not make sense.

Please also see my past answer and an article where I explain how thread invocation works under the hood:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^],
Simple Blocking Queue for Thread Communication and Inter-thread Invocation[^].

—SA
 
Share this answer
 
You're my singing up new threads written you Invoke code. You're telling the UI thread to execute a method, so yes, the UI thread can only execute one method at a time.

Events are normally raised on the UI thread, so you're probably needlessly Invoking those methods.

The trick is redesign your code so the actual work being done, apart from manipulating controls, is being done on threads you spin up for that purpose.
 
Share this answer
 
v2
Comments
Sergey Alexandrovich Kryukov 20-Oct-13 21:00pm    
I'm really sorry, but "Events are normally raised on the UI thread" is a totally wrong statement. It depends how the user uses the object, in what thread. This is something about network, and network operation, just the opposite, should never be conducted on UI thread, so I hope OP did it right. InvokeRequired is not called, and, if the code is correct, this is the indication that OP knows that the thread is a non-UI thread and hence use Invoke unconditionally. Not calling InvokeRequired is absolutely correct if it is known, by design, that the calling code is executed non in the UI thread.

As to the OP's question, the think is that Control.Invoke or Control.BeginInvoke delegates handling to the UI thread anyway, so serialization of the handlers is quite natural, handling in parallel would simply make no sense.
Dave Kreskowiak 20-Oct-13 21:32pm    
OK, yes, events are normally raised in the thread that the object raising them was created in.

For the vast majority of these single-threaded newbies, that's going to be the UI thread. In the body of the OP's question, it doesn't sound like he knows how the event system works, nor completely why he's invoking back to the UI thread. I also noted the lack of IsInvokeRequired() calls.

Granted, the code snippet is incomplete and I made certain assumptions.

But, the clue to what's going on is the subject line the OP used. This can be caused by two different situations. Either the event is being raised on the UI thread and he's Invoking back to the UI thread (completely unnecessary), or the events being raised on the secondary thread(s) are coming so fast as to be overwhelming the UI thread with Invoke requests.
Yesudasan Moses 21-Oct-13 2:50am    
If I don't invoking the UI, It will show this error....
"Cross-thread operation not valid: Control 'Label1' accessed from a thread other than the thread it was created on"

Moreover, Invokerequired doesn't solve my problem,,,, My issue is The event doesnt happen until the last event is finished... Is there any way to collect the parameter values and end the event,,, then process the parameters,,,
Can I use a queue for this ??
Dave Kreskowiak 21-Oct-13 7:34am    
Al this does is sent the text of a label. This shouldn't be taking very long at all, so I'm wondering what the problem is??

The event handler ends when the code reaches the end of the method. Invoke is a blocking call, so you might want to switch to BeginInvoke. It's worth a try I guess, but the state on screen will lag behind the actual state of your system.

I'm wondering what the real bottleneck is. Your just setting the text of a label, so what's driving this search for another solution??
Yesudasan Moses 21-Oct-13 7:38am    
Nop,,, There are lot of coding inside this,,, I removed it all for making it brief....
The reason for the slowness is Inside this event, There is a checking of Outlook Contacts for the Caller name of Incoming call ,,,

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900