Pages Menu
TwitterRssFacebook

Posted by on Jul 29, 2014 in Development, Skype for Business® (Lync®)

Lync Development and Asynchronous Programming

Lync Development and Asynchronous Programming

Introduction

Asynchronous Programming is an important construct in the world of Lync Development. If you’re already happy with programming in Async, then you can skip this blog post. However, if you’d like a refresher, or are new to the idea – you definitely need to make sure you’re happy with the ideas here before you move on, especially to Lync Server development using UCMA.

What is Asynchronous Programming?

Think about what your computer/phone/tablet is doing right now. It’s showing this page. It’s also keeping track of time, monitoring your mouse/touchscreen, clearing up some unused bit of memory, writing log files, and a million other things, all at the same time. It can do this because the processor is capable of switching very rapidly between different threads. Each application has at least one thread – and in the simplest applications only one thread, where all the work gets done.

But applications can have more than one thread, and that’s where it gets interesting. You might be familier with the BackgroundWorker object in WPF programming. Previously in Windows programming* when you were performing some long-running operation such as loading a file from disk, because the application was waiting for this to finish, any other request – such as the user clicking on buttons – had to wait. (this results in the application going all “not responding” on you). The BackgroundWorker lets you perform some long-running task in the background but still respond to UI events. It does this by creating a new thread and doing your long running task there – rather than on the application’s main thread, which is where all the UI elements are.

*that’s not quite true. Prior to the BackgroundWorker, threads still existed, so you could write nice applications that were multi-threaded. It’s just that no-one did.

Asynchronous Programming is a big topic that’s been well covered elsewhere, so I won’t go into more detail here.

Why Do I Need To Know It?

Because nearly all of the methods in the UCMA and PersistentChat APIs, and quite a lot of the Desktop API – are asynchronous.

Why? Lync is an interconnected system of disparate parts. If you send a message to someone, your message might be hitting different servers, different networks, even different continents. Internally, your request to send a message is translated into a SIP message, which is a chatty request-response architecture. Eventually a SIP message will come back to tell you that your message was successfully delivered.

If all this was done synchronously (the opposite of asynchronously) your application would have to wait around for every single action to complete, and wouldn’t be able to do anything else whilst it was waiting. This would severely affect the ability of your application to scale and you’d soon hit performance problems.

Begin..End

So, we now know that asynchronous programming is a Good Thing. The Lync Development APIs implement this using the Begin..End pattern. Every asynchronous method has a Begin and a End method associated with it. When you want to call the method, you call the Begin method that’s associated with it. This method returns immediately (so that you’re not waiting around on your main thread), but what’s actually happened is that it’s created a new thread and started running. When it finishes, it needs a way of telling you that it’s done, and giving you any data as a result of it running. When you call Begin you also specify the name of the method to call when the task is done – this is usually named End. You can also pass one more piece of information, an Object, which is available to you in the End method. This comes in handy later on…

Let’s look at an example: In UCMA, to send an instant message to an existing conversation, you need to use the InstantMessageFlow class. If you look at the methods of that class (from MSDN) you won’t see a SendMessage method. Instead you’ll see a BeginSendMessage and a EndSendMessage:

InstantMessageFlowMethods

The signature for the BeginSendMessage starts with the information needed to actually do the sending (the message) but also contains two arguments common to all Begin message: userCallback and state. userCallback is the method we want to invoke when the operation has finished. state is the Object we can pass in for later.

To send a message, you call BeginSendMessage, passing it everything it needs… AND the name of the method you want it to call once it’s finished, in this case EndBeginSendMessage. I’m also passing in the flow object as the state. If it’s not obvious why yet, don’t worry:

private void MyMethod() {
//do some stuff
var flow = GetFlowFromSomewhere();
var message = GetMessageFromSomewhere();
flow.BeginSendInstantMessage(message, EndBeginSendInstanceMessage, flow);
//do some other things....
}
private static void EndBeginSendInstantMessage(IAsyncResult ar)
{
try
{
InstantMessagingFlow flow = (InstantMessagingFlow)ar.AsyncState;
flow.EndSendInstantMessage(ar);
}
catch (Exception ex)
{
//do something with this error
}
}

If we were to run MyMethod, the BeginSendMessage would run and complete immediately, and whatever code we had in line 9 onwards would execute. At some point in the future, once Lync had finished sending our message, the EndBeginSendMessage method would start to run.

Now, with Async operations, it’s not fully over until you End it. That is to say, even though the EndBeginSendMessage method has started running, that doesn’t 100% mean your message was delivered. If something went wrong and Lync wants to throw an exception at you about it, it won’t just throw it in the main thread (because that would be terribly confusing). You have to call the method EndSendMessage to “finish off” the process. If anything went wrong, this is where an exception will be thrown, so it’s very important to always surround the End method calls with try..catch loops.

Now, about the line just above that, doing some explicit casting? Well, in order to call EndSendMessage you need to have the flow object, because that’s where the method is. This is one of the reasons you pass the state through to the End method: so that you can use it later. It saves you from having to define a bunch of global variables (which would also work, but might be seen as bad practice). The other reason for doing this.. imagine that you want to send a message to lots of different people in lots of different conversations. You’d call BeginSendMessage many times (maybe in a loop) – but all those calls would eventually all come back to EndBeginSendMessage – lots of times. Each time you need to make sure you call EndSendMessage using the correct flow object for that conversation. By passing it with the message, you don’t have any thinking to do, and you’ll always have the correct object.

Now that you know the traditional approach, here are some alternatives you can use to achieve the same thing.

Lambda Expressions

Here’s the same code, using a lambda expression.

private void MyMethod() {
//do some stuff
var flow = GetFlowFromSomewhere();
var message = GetMessageFromSomewhere();
flow.BeginSendInstantMessage(message, result =>
{
try
{
flow.EndSendInstantMessage(result)
}
catch (Exception ex)
{
//do something with this error
}
},null);
//do some other things....
}
view raw Async lambda hosted with ❤ by GitHub

This will still return immediately, and the “End” part will still run in a new thread. It’s just a different way of writing it that some people prefer because it’s more concise and easier to see the flow of the application.

Task..Await

If you’re only writing for Lync Server 2013, and only using UCMA 4 – then it could be your lucky day! .NET introduced the Task Parallel Library, which makes calling asynchronous methods much easier. If you can convert your Begin..End methods into Tasks, then calling them asynchronously is as simple as:

private void MyMethod()
{
await CallLongRunningTaskAsync();
//this code runs AFTER the task has completed;
}
view raw asynctasks hosted with ❤ by GitHub

The await keyword tells the code to wait until it’s finished before it carries on. “Now wait a moment!” (I hear you cry.) “That’s the same thing as if we didn’t run it asynchronously – the code will wait until the task has finished”. And you’d be right, except that the long running task is still happening on a new thread. Waiting for it to finish is probably exactly what we want our program to do…we just don’t want it to block everything else from happening in the meantime. This way, it’s still happening on a new task, we can still respond to other events in the main thread, and we still get to keep our program flow, without having to bounce around lots of different End methods, or create lots of lambda expressions. There’s lots of other tricks we can do with Tasks as well which help with scalability, such as starting off a whole collection of Tasks, and then only continuing when they all complete.

There’s just one catch (apart from it only being available on UCMA 4). To use this approach (i.e. to support the await keyword) all your asynchronous methods must support Tasks, which UCMA 4 doesn’t. It’s actually quite easy to create extension methods though: here’s how you would extend the SendMessage method from earlier to support Tasks:

public static Task SendMessageAsync(this InstantMessagingFlow flow, IMessage message)
{
return Task.Factory.FromAsync(flow.BeginSendMessage,
flow.EndSendMessage, message, null);
}
view raw asynctask hosted with ❤ by GitHub

See, it’s really not that hard, and would mean that you could now call
await SendMessageAsync(flow,message)
and be done with it.

What’s even better is that Michael Greenlee has put together a whole collection of extension methods for Lync which you can use. The most popular methods are covered, and even if you come across one that isn’t, you can use the many examples there to create your own.

Doing it Wrong: Chaining

You might come across this, in blog posts, examples, maybe even production code:

public void MyMethod()
{
flow.EndSendMessage(flow.BeginSendMessage,null,null);
}
view raw async.chaining hosted with ❤ by GitHub

This is an example of chaining together the Begin and the End into one line of code.

The effect of this is to force the operation to become synchronous – your code will block (wait without doing anything else) until the operation has finished.

This is Bad! It’s bad because it can’t scale, and you’ll lock up resources. Also, there is a chance that the End method is never received by your application. It’s rare, and it shouldn’t happen, but it’s not impossible. If you’ve chained together your methods, your application will block forever, waiting…

Now that you know why it’s bad – it’s up to you if you decide to use it in Proof of Concepts, quick tests, and in producing sample code to replicate problems (it does result in much neater code!). But you shouldn’t use it as a pattern for production development.

Written by Tom Morgan

Tom is a Microsoft Teams Platform developer and Microsoft MVP who has been blogging for over a decade. Find out more.
Buy the book: Building and Developing Apps & Bots for Microsoft Teams. Now available to purchase online with free updates.

1 Comment

  1. Hi Tom, How can I add Is_Typing message if I am following Async programming .Can I add it within
    SendInstantMessageAsync method like below.

    public static Task
    SendInstantMessageAsync(this InstantMessagingFlow flow,
    string textBody)
    {

    return Task.Factory.FromAsync(
    flow.BeginSendInstantMessage,
    flow.EndSendInstantMessage, textBody, flow.LocalComposingState = ComposingState.Composing);
    }

Trackbacks/Pingbacks

  1. Lync Desktop Development: Finding your way around the Client SDK | thoughtstuff | Tom Morgan - […] Important: lots of the methods in this SDK start with Begin. If you’re not sure why that is, or…

Post a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.