About SharePoint Event Receiver. 学习笔记.
Summarized from http://hristopavlov.wordpress.com/2009/02/24/understanding-sharepoint-event-receivers/
- All list item, list and web event receivers in SharePoint [with the exception of the ListItemFileConverted receiver(除了这个类型)] are run from the SPRequest unmanaged class.
- There are two types of event receivers – synchronous (such as ItemAdding and ItemUpdating) and asynchronous (such as ItemAdded and ItemUpdated).
- Because the event receivers are implemented in managed code, the unmanaged SPRequest class needs a way to invoke them. This is done via the ISPEventManager COM interface which is implemented by the Microsoft.SharePoint.SPEventManager internal class.
1 [ComImport, SuppressUnmanagedCodeSecurity, InterfaceType((short)1), Guid("BDEADF0F-C265-11D0-BCED-00A0C90AB50F")]
2
3 public interface ISPEventManager
4
5 {
6
7 [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
8
9 void ExecuteItemEventReceivers(
10
11 ref byte[] userToken, ref objecteventReceivers, ref ItemEventReceiverParams itemEventParams,
12
13 out objectchangedFields, outEventReceiverResult eventResult, out stringerrorMessage);
14
15
16
17 [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
18
19 void EnqueueItemEventReceivers(ref byte[] userToken, ref objecteventReceivers, ref ItemEventReceiverParams itemEventParams);
20
21
22
23 [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
24
25 void ExecuteListEventReceivers(
26
27 ref byte[] userToken, ref objecteventReceivers, ref ListEventReceiverParams ListEventParams,
28
29 outEventReceiverResult eventResult, out stringerrorMessage);
30
31
32
33 [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
34
35 void EnqueueListEventReceivers(ref byte[] userToken, ref objecteventReceivers, ref ListEventReceiverParams ListEventParams);
36
37
38
39 [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
40
41 void ExecuteWebEventReceivers(
42
43 ref byte[] userToken, ref objecteventReceivers, ref WebEventReceiverParams webEventParams,
44
45 outEventReceiverResult eventResult, out stringerrorMessage);
46
47
48
49 [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
50
51 void EnqueueWebEventReceivers(ref byte[] userToken, ref objecteventReceivers, ref WebEventReceiverParams webEventParams);
52
53 }
54 - Both synchronous and asynchronous event receivers will execute in the same process that has made the change that resulted in the event receivers being called.
同步和非同步的event receiver都在触发event进程中被执行的. - The asynchronous event receivers may need some time to complete (could be a lot of time) and if you close your MyWinFormsApp.exe immediately after you have added the file, and while the event receivers are still running, what will happen is that they will be terminated and some of them may not run at all.
- The asynchronous event receivers will be run in their own thread from the System.Threading.ThreadPool.
Switching between threads is a very resource intensive operation and if you have 100 threads running in your application or in IIS, this will pretty much slow down the process to a crawl.
I(Hristo Pavlov)’ve seen this happening with a custom built migration tool that moves documents from one document library to another. There were some heavy ItemAdded event receivers and after few hundreds files were moved for a minute or so, it took another 45 minutes for the event receivers to complete. The migration would have been faster if after adding each file the migration tool was waiting for the event receivers to complete because after adding all the files at once 90+% of the time the process was spending in switching between the few hundred threads and only up to 10% were the actual threads running the event receivers. - The lifespan for the SPItemEventProperties that are passed to all item event receivers.
a. All synchronous event receivers will share the same properties,
b. All asynchronous event receivers will share different instance of the properties.
c. The unmanaged SPRequest class will keep the changes to the properties done by the synchronous event receivers and will pass them to the asynchronous event receivers.
This could only(only?) be done from an ItemAdding or ItemUpdating event receiver. You could add anything you want to the AfterProperties collection and the information you have added will be availabe as AfterProperties in the ItemAdded and ItemUpdated event receivers.
d. SPItemEventProperties class actually implements IDisposable and disposes the allocated site or web. The SPEventManager class makes sure to call Dispose() after the batch of event receivers have executed. - To use them you need to create your event receiver class to inherit from the SPSynchronousReceiver class and override the ItemAddedSynchronously method:
a.public class SPTestReceiver : SPSynchronousReceiver
{
protected override void ItemAddedSynchronously(SPItemEventProperties properties)
{
// Your code goes here
}
// Your other item receiver overrides go here
}
b.using (SPSite site = new SPSite(“http://server/sites/test”))
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists["Shared Documents"];
SPFile file = list.RootFolder.Files.Add(fileName, fileBytes);
SPSynchronousReceiver.WaitForItemAddedReceivers(list, file.Item.ID);
}
c. 可以在页面上添加一个web control等待ItemAdded事件结束.<%@Register TagPrefix=”SharePointInternals”
Assembly=”SharePointInternals.SynchronousItemAdded, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d7dbdc19a16aed51″
namespace=”SharePointInternals.WebControls”%>
…
<asp:Content ContentPlaceHolderId=”PlaceHolderMain” runat=”server”>
<SharePointInternals:WaitForItemAdded ID=”waitForItemAdded1″ runat=”server”/>
…
</asp:Content>这里要注意添加control的位置.
If we add the web control to the ListFormTemplate used by the ListFormWebPart from EditForm.aspx, then it will wait for the event receivers to complete, but at this stage the ListItem would have been already loaded in the SPContext and the EditForm.aspx will show the field values of the list item before the ItemAdded event receivers have completed. If any of them have updated the list item then pressing OK on the EditForm.aspx will actually cause an exception:
The file … has been modified by … on …
(解释, 这里作者想要在ItemAdded 的 receiver执行完毕, 在editform中显示item的metadata. 如果把webcontrol添加在ListFormTemplate中, ListFormWebPart会调用ListFormTemplate, EditForm.aspx会调用ListFormTemplate, 这样EditForm.aspx在显示前也会等待Receiver执行完毕. 但是在Receiver执行之前, SPContext应经加载Item完毕. 也就是说, 显示的Item和他的metadata已经过期失效. ) -
GENE(笔记者)添加, 提升权限是线程级的, 每个Receiver都是在独立的线程内运行的, 因此编写EventReiver的代码, 要注意权限问题, 或者在Receiver内注意提升权限.
浙公网安备 33010602011771号