10

Let's say I set up an ItemAdded event receiver with a sequence number of 12345. On this list there're two other event receivers that run before it; one for ItemAdding, and an earlier one for ItemAdded.

Here is what the execution would look like:

Event      | Sequence | Name
--------------------------------------------
ItemAdding | 100      | Schedule parade
ItemAdded  | 100      | Begin parade
ItemAdded  | 12345    | Fire confetti cannon

Will my event receiver run if either (or both) of the two earlier event receivers throw an error?

1
  • I should note that this is for a purely theoretical solution; I'm deciding whether or not to use an Event Receiver to solve a problem in a program that hasn't started development (not just really lazy). :)
    – Stu Pegg
    Dec 19, 2011 at 17:26

2 Answers 2

5

Your discussion intrigued me and I decided to test it eventually :)

I wrote 4 event receivers - ReceiverS1, ReceiverS2, ReceiverA1, ReceiverA2, sync (seq num 100), sync (seq num 101), async (seq num 100), async (seq num 101) accordingly. I added receivers and verified using sharepoint manager that all settings correct. This is code for receivers:

public class ReceiverS1 : SPItemEventReceiver
{
    public override void ItemAdding(SPItemEventProperties properties)
    {
        properties.AfterProperties["event_x0020_test"] = "ReceiverS1 started: " + DateTime.Now.ToLongTimeString() + "<br>";
        //properties.AfterProperties["event_x0020_test"] = (string)properties.AfterProperties["event_x0020_test"] + "Throwing in sync ItemAdding: ReceiverS1 " + "<br>";
        //throw new Exception("something wrong happened");
    }
}

public class ReceiverS2 : SPItemEventReceiver
{
    public override void ItemAdding(SPItemEventProperties properties)
    {
        if (properties.AfterProperties["event_x0020_test"] != null)
        {
            var text = (string)properties.AfterProperties["event_x0020_test"];
            properties.AfterProperties["event_x0020_test"] = text + " ReceiverS2 started: " + DateTime.Now.ToLongTimeString() + "<br>";
        }
    }
}

public class ReceiverA1 : SPItemEventReceiver
{
    public override void ItemAdded(SPItemEventProperties properties)
    {
        if (properties.ListItem["event test"] != null)
        {
            var text = (string) properties.ListItem["event test"];
            properties.ListItem["event test"] = text + " ReceiverA1 started: " + DateTime.Now.ToLongTimeString() +"<br>";
            //properties.ListItem["event test"] = (string)properties.ListItem["event test"] + "Throwing in async ItemAdded: ReceiverA1 " + "<br>";
            properties.ListItem.Update();
            Thread.Sleep(10000);
            //throw new Exception("something wrong happened");
        }
    }
}
public class ReceiverA2 : SPItemEventReceiver
{
    public override void ItemAdded(SPItemEventProperties properties)
    {
        if (properties.ListItem["event test"] != null)
        {
            var text = (string) properties.ListItem["event test"];
            properties.ListItem["event test"] = text + " ReceiverA2 started: " + DateTime.Now.ToLongTimeString() +"<br>";
            properties.ListItem.Update();
        }
    }
}

event_x0020_test is a rich field in some list.
Here is a result from the first test:

ReceiverS1 started: 7:40:29 PM
ReceiverS2 started: 7:40:29 PM
ReceiverA1 started: 7:40:29 PM
ReceiverA2 started: 7:40:39 PM

As you can see from time stamp, A2 (async, 101) receiver started work only when A1 ended (10sec diff). I assume "asynchronous" means that all this async receivers run in one, but separate thread (not one thread for every async receiver).
Next exception test - I uncommented all lines and replace .dll and here is the result:

ReceiverS1 started: 7:42:12 PM
Throwing in sync ItemAdding: ReceiverS1
ReceiverS2 started: 7:42:12 PM
ReceiverA1 started: 7:42:12 PM
Throwing in async ItemAdded: ReceiverA1
ReceiverA2 started: 7:42:22 PM

Even in some of receivers there is an error, all other work as expected, I suppose this is a good and correct behavior.
Hope this helps :)

EDIT
msdn is saying that for every async after-receiver there is a separate thread, I added Thread Id to output test it:

properties.ListItem["event test"] = text + " ReceiverA1 started: " + DateTime.Now.ToLongTimeString() + " Thread ID:" + Thread.CurrentThread.ManagedThreadId.ToString() + "<br>";

And here is the result:

ReceiverS1 started: 10:15:10 AM Thread ID:13
ReceiverS2 started: 10:15:10 AM Thread ID:13
ReceiverA1 started: 10:15:11 AM Thread ID:5
ReceiverA2 started: 10:15:21 AM Thread ID:5

ReceiverA1 and ReceiverA2 both async (I double-checked it using sp manager). It seems that information on msdn is not correct.

1
  • Thanks for going to the trouble of building a test project. :)
    – Stu Pegg
    Dec 25, 2011 at 21:07
3

I assume that by Error you mean an Unhandled Exception. So "What happens" depends on which thread they run as each thread has an independent execution path.

ItemAdded is an After-Event which may be configured as synchronous or asynchronous. Asynchronous After event executes on a thread that is different from the one in which the triggering action is running. Asynchronous After event receiver threads are initiated in sequential order based on the sequence number. However, there is no guarantee that they will finish in that same order.

So one Asynchronous receiver will not block other receiver(s) if there is some error in it as they are on different threads.

ItemAdding event is a Before-event and is always synchronous. A synchronous event is executed in the same thread in which the triggering action is occurring and any error in it may terminate the thread and thus preventing further execution.

Having said that, below is the output:

  • If error in ItemAdding and ItemAdded(Synchronous), next receivers in sequence will not run.
  • If error in ItemAdded(Asynchronous), next receivers in sequence will run.

Below is the event pipeline as provided by Microsoft.For more details : http://msdn.microsoft.com/en-us/library/gg749858.aspx

enter image description here

5
  • So essentially you're saying that asynchronous event handlers for the same event are also asynchronous to each other? Which would mean the Sequence Number on asynchronous event definitions is largely redundant...
    – Stu Pegg
    Dec 20, 2011 at 16:53
  • the sequence number for asynchronous only determines the start of the event receiver and not end of its execution.So it is possible that receiver with lower sequence ends after the one with higher sequence. Dec 20, 2011 at 16:56
  • It appears the testing done by @Kai contradicts your answer.
    – Stu Pegg
    Dec 25, 2011 at 21:08
  • As per Microsoft,there is separate thread for every async receiver(unlike @Kai said).See my edit above. Also, I don't see if he considered the case of running async receivers in synchronization(a new SP2010 feature). Dec 26, 2011 at 3:41
  • Its very interesting indeed, I do some more tests (see edit). I didn't test async receivers in synchronization because I think they would behave similarly as sync before-receivers. Dec 26, 2011 at 7:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.