I have a couple of question regarding developing multithreading webparts in Sharepoint. First, let me explain the idea. I have a page with 5-7 different webparts. These webparts are constructed all in the same way, which means:
a) the retrieve some data from some SPLists
b) transform that data to xml
c) execute xslt transformation to generate html
d) output html content in the RenderContents method
This process requires approximately 500ms for a single webpart.
Now my idea is to do some performance tuning using threads. All the process described before could be executed by a thread in the best case in an early method of the execution pipe (ex. OnLoad) or in the worst case in the OnPreRender method. In the RenderContents method I could in the worst case wait for the thread to finish (of course here I would implement some timeout logic).
Q1) Using this technique should increase the performance of the page, right?
My assumption: I have 5 webparts on the page and one webpart takes 500ms
Before: the execution time would be 5*500ms = 2500ms.
Afterwards: Max(wp1, wp2, wp3, wp4, wp5) which in my case would be 500ms.
Now, my first question: Q2) Do I am right? If not, why?
Now let’s speak more detail about the implementation. Which technique should I use?
a) Create an new Thread and then call Thread.join()
b) use ThreadPool
c) Or call Page.RegisterAsyncTask in the OnPreRender
At this point I have a few other questions:
Q3) Since, I am using SPSite and I was reading that this Object is based on COM can I use ThreadPool or Page.RegisterAsyncTask? In some blog I was reading that ThreadPool does not support COM object, because of the Apartment mode (MTA vs STA). Moreover I think that Page.RegisterAsyncTask is also using ThreadPool.
Q4) Which kind of implementation/architecture would you advise me?
Q5) If I would use Page.RegisterAsyncTask in the OnPreRender method do I am sure that in the method RenderContents is only called when all tasks are finished?
I tried the implementation with Threads, but it seems not working. As soon as I am trying to access the SpSite I am getting following exception:
at Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx) at Microsoft.SharePoint.Library.SPRequest.GetTokenOfCurrentUser(Boolean bWindowsMode, String bstrLogin, String bstrUserKey, String bstrRoles, UInt32 ulRoleCount) at Microsoft.SharePoint.SPSite.InitUserToken(SPRequest request) at Microsoft.SharePoint.SPSite.SPSiteConstructor(SPFarm farm, Guid applicationId, Guid contentDatabaseId, Guid siteId, Guid siteSubscriptionId, SPUrlZone zone, Uri requestUri, String serverRelativeUrl, Boolean hostHeaderIsSiteName, SPUserToken userToken) at Microsoft.SharePoint.SPSite..ctor(SPFarm farm, Uri requestUri, Boolean contextSite, SPUserToken userToken) at Microsoft.SharePoint.SPSite..ctor(String requestUrl)
I tried the implementation with Page.RegisterAsyncTask but I am getting following exception:
Attempted to make calls on more than one thread in single threaded mode. (Exception from HRESULT: 0x80010102 (RPC_E_ATTEMPTED_MULTITHREAD)) at Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx) at Microsoft.SharePoint.Library.SPRequest.SetIPAddr(String bstrIPAddr) at Microsoft.SharePoint.SPGlobal.CreateSPRequestAndSetIdentity(SPSite site, String name, Boolean bNotGlobalAdminCode, String strUrl, Boolean bNotAddToContext, Byte UserToken, String userName, Boolean bIgnoreTokenTimeout, Boolean bAsAnonymous) at Microsoft.SharePoint.SPWeb.InitializeSPRequest() at Microsoft.SharePoint.SPWeb.GetList(String strUrl)
How can I implement such an architecture?