Search code examples
c#skypelyncskypedeveloperlync-client-sdk

Lync SDK BeginSendMessage AsyncCallback


I use the Lync SDK 2013 and want to send an instant message to a contact.

    private void SuppressIncomingConversation(Conversation conversation)
    {
        InstantMessageModality instantMessageModality = conversation.Modalities[ModalityTypes.InstantMessage] as InstantMessageModality;
        instantMessageModality.BeginSendMessage("No.", null, null);
        conversation.End();
    }

The second parameter of BeginSendMessage is a callback of type AsyncCallback.

The code above works fine but should I put conversation.End(); into the callback parameter?

How can I do this, I tried () => conversation.End() but the callback needs to take some arguments.


Solution

  • The async API in the Lync Client 2013 API are a older style of the a standard C# async API.

    So the API has StartXxx and a matching EndXxx for all ASYNC operations. You need to call the EndXxx when the AsyncCallback completes.

    There are actually a number of ways to handle this. A common way is to provide a callback to call the EndXxx method.

    e.g.

    InstantMessageModality instantMessageModality = conversation.Modalities[ModalityTypes.InstantMessage] as InstantMessageModality;
    instantMessageModality.BeginSendMessage("No.", ar =>
        {
            try
            {
                instantMessageModality.EndSendMessage(ar);
            }
            catch (Exception ex)
            {
                // log ex message
            }
        });
    

    Also you may like to check that your only dealing with "audio / video calls" only... As you may be ending other types of calls...

    You do this be checking that the call has a AVModality e.g.

    if (conversation.Modalities.ContainsKey(ModalityTypes.AudioVideo))
    

    Another problem is that the conversation may be in a state that can't do the async operation you want, you can test if you are allowed to do your operation with the CanInvoke method. e.g

    if (conversation.Modalities.TryGetValue(ModalityTypes.InstantMessage, out var modality))
    {
        if (modality is InstantMessageModality instantMessageModality && instantMessageModality.CanInvoke(ModalityAction.SendInstantMessage))
        {
            instantMessageModality.BeginSendMessage("No.", ar =>
            {
                try
                {
                    instantMessageModality.EndSendMessage(ar);
                }
                catch (Exception ex)
                {
                    // log ex message
                }
            }, null);
        }
    }
    

    And one last point, you can also provide a "reason" (like Busy) for declaring the call rather than using End to terminate the conversation...

    e.g.

    if (conversation.Modalities.TryGetValue(ModalityTypes.AudioVideo, out var modality))
    {
        if (modality is AVModality avModality && avModality.CanInvoke(ModalityAction.Disconnect))
        {
            avModality.BeginDisconnect(ModalityDisconnectReason.Busy, ar =>
            {
                try
                {
                    avModality.EndDisconnect(ar);
                }
                catch (Exception ex)
                {
                    // log ex message
                }
            }, null);
        }
        else
        {
            // fallback
            conversation.End();
        }
    }