Asynchronous programming in Lync SDK

Core concepts

Learn about using callback delegated methods to complete asynchronous Microsoft Lync 2013 API operations and obtain operation results.

Applies to: Lync 2013 | Lync Server 2013

In this article
Asynchronous operations in the Lync API
Calling asynchronous Lync methods synchronously
Calling Lync methods asynchronously
Additional resources

Asynchronous operations in the Lync API

Asynchronous operations in Lync follow the standard asynchronous programming pattern. That is, the pattern is implemented by the BeginOperationName and EndOperationName methods. The EndOperationName method should be called in a callback method whose reference you pass in the BeginOperationName method as a callback argument. For more information about this pattern, see Asynchronous Programming Overview.

An EndOperationName method returns void when there is no operation-generated data. Otherwise, the returned value is a set of values generated by the operation itself. If you create a single all-purpose System.AsyncCallback method, you can pass an operation-specific state in the BeginOperationName method and your callback method can get the operation state and run appropriate logic. For example, the contact search operation begins with a call to the ContactManager.BeginSearch method. When the search operation is finished, Lync Server 2013 sends a collection of contacts that are obtained by calling the ContactManager.EndSearch method. For more information about how to pass an application state into a callback method, see Using an AsyncCallback Delegate and State Object.

Calling asynchronous Lync methods synchronously

It's not a good practice to block your UI thread by calling an asynchronous Lync 2013 API by using a synchronous code pattern. In some cases, the asynchronous operation succeeds when it's called in this manner. Other times, the operation fails because it's called using the synchronous pattern. In a typical synchronous pattern, you code the call to the object.EndOperationName first and call the object.BeginOperationName inside the EndOperationName method call so that the System.IAsyncResult return value of the BeginOperationName is the single argument value of the EndOperationName method. Because you're calling EndOperationName on the UI thread, the thread is blocked until the operation is completed.

For example, signing a user in to Lync 2013 by starting the sign-in operation using the syntax: _lyncClient.EndSignIn(_lyncClient.BeginSignIn(null, null, null, null, null)); blocks your UI until the operation is completed. As long as the UI is blocked, the user cannot start any Lync operations that depend on a signed-in client. However, coding the operation in this manner is not a reliable way to sign the user in.

Calling Lync methods asynchronously

In general, Lync 2013 API operations change the state of the object on which the operation is called. Such state changes involve asynchronous updates from server and raise related events that should be used to get the new object state. If the object state is used to set the state of a UI control, use the event callback method to update the UI control. The callback method is invoked on the API platform thread to update controls that are owned by the UI thread. This cross-threading operation is not thread-safe, so you have to create a UI updating method that is invoked by the event callback using a delegate. For information about how to make thread-safe calls, see How to: Make thread-safe calls to Windows Forms controls.

A better way to sign the user in is to register for Client.StateChanged events, default all UI controls to disabled, call the sign-in operation asynchronously, and then enable UI controls in the StateChanged event handler when the client state is ClientState.SignedIn.

The following example uses an asynchronous code pattern to sign a user in to Lync 2013. The EndSignIn method is called on the platform thread by passing the call in the callback argument of BeginSignIn so that the lambda expression can be invoked on the platform thread when the operation is complete.

        public void SignIn(string SIP, string Domain, string Password)
        {
            try
            {
                _lyncClient = Microsoft.Lync.Model.LyncClient.GetClient();
                _lyncClient.StateChanged += _LyncClient_ClientStateChanged;
                if (_lyncClient.State == ClientState.SignedOut)
                {
                    _LyncClient.BeginSignIn(
                        SIP,
                        Domain,
                        Password,
                        (ar) =>
                        {
                            _LyncClient.EndSignIn(ar);
                        }
                        ,
                        null);
                }
                else if (_lyncClient.State == ClientState.SignedIn)
                {
                    //Enable UI controls 
                }
            }
            catch (NotStartedByUserException)
            {
                throw new Exception("Lync is not running");
            }
        }

    void _LyncClient_ClientStateChanged(Object source, ClientStateChangedEventArgs data)
    {
        if (data.NewState == ClientState.SignedIn)
        {
            //Enable UI controls 
        }
        if (data.NewState == ClientState.SignedOut)
        {
            //Disable UI controls UI controls 
        }
    }

See also