How to: Create a multi-threaded managed SIP application

Lync 2013

Learn how to create a multi-threaded SIP application in a Microsoft Lync Server 2013 deployment.

Last modified: August 16, 2013

Applies to: Lync Server 2013

For performance and efficiency, Lync Server 2013 events can be handled with worker threads from the .NET Framework thread pool.

A simple approach is to use the .NET Framework thread pool and queue each event from the server (for example, use a call from Dispatch) as a user work item. In the next code sample, the server signals an event with the WaitHandle property that is provided by the ServerAgent instance. After the event is signaled, the application attempts to create a worker thread from the thread pool, which is then used to service the event. The ProcessEvent(Object) event callback method is passed to the thread, which removes the event (the dispatch) from the server queue and processes it by passing the SIP message to the method that is specified in the Microsoft SIP Processing Language (MSPL) call to Dispatch.

The next code sample demonstrates the basic structure that is used for threading dispatches from the server. It can be called directly from the Main() (entry point) method of your application, taking an instance of ServerAgent as a parameter.

public void LCServerEventHandler(ServerAgent sa)
{
   ManualResetEvent autoResetEvent = new ManualResetEvent(false);
   WaitHandle[] handleArray = new WaitHandle[] {
                                 myAppServerAgent.WaitHandle,
                                 manualResetEvent
                              };

   WaitCallback waitCallback = new WaitCallback(myAppServerAgent.ProcessEvent);

   while (true)
   {
      int signaledEvent = WaitHandle.WaitAny(handleArray);

      if (signaledEvent == 0)  // The server event wait handle (index = 0) in handleArray was signaled
      {

          // Schedule a worker thread to process the server event
          try
          {
             if (!ThreadPool.QueueUserWorkItem(waitCallBack))
             {
                 Console.WriteLine("QueueUserWorkItem fails, quitting.");
                 return;
             }

          }
          catch (Exception e)
          {
             Console.WriteLine("Unexpected exception: {0}\n{1}",
                               e.Message,
                               e.StackTrace);
          }
       }
       else // Manual reset event handle (index = 1) in handle array was signaled
       {
          Console.WriteLine("Quit handle signaled, worker will quit now\n");
          break;
       }
   }
}
Show: