There are a few options to serialize handling of the events which may be fired concurrently from multiple threads, or on the same thread via re-enrancy/recursion.
One of the options is to use a task scheduler. In your scenario, the purpose of the task scheduler would be to queue callbacks for later serial execution. A well known conceptual examples of the task schedulers like that are WinForms message loop (starting with Application.Run, queuing with Control.BeginInvoke) and WPF Dispatcher loop (starting with Dispatcher.Run, queuing with Dispatcher.BeginInvoke or Dispatcher.InvokeAsync).
A less know but very useful implementation of a TPL task scheduler is StaTaskScheduler by Stephen Toub. I posted some code based upon it here and here (the latter one is from a closely question, Queuing Actions/Delegates for Asyncronous Execution).
Another option is described here: Task sequencing and re-entracy.
In this case, handlers are composed as tasks, each new handler is started when the previous task has completed.