通过实现 PageAsyncTask 在 MOSS 页面中实现多线程






4.80/5 (4投票s)
使用PageAsyncTask实现Web Part并行渲染,代替RegisterWorkItem。
引言
目前,越来越多的公司开始迁移到SharePoint 2007。作为SharePoint应用程序的基础,Web Part需要更多关注,因为它们会根据业务或用户需求进行定制。让我们讨论一下如何将异步Web Part从SharePoint 2003升级到SharePoint 2007的一些问题。
背景
当开发者重新编译一个使用Microsoft.SharePoint.WebPartPages.WebPart.RegisterWorkItem
实现多线程渲染的Web Part时,他们会发现一个警告:'Microsoft.SharePoint.WebPartPages.WebPart.RegisterWorkItemCallback(System.Threading.WaitCallback, object)' is obsolete: 'Use Page.RegisterAsyncTask instead.'。
实现Page.RegisterAsyncTask
很简单,就像MSDN所说的那样。挑战在于如何使其在SharePoint Web Part页面中工作…
首先,让我们过一下源代码
该项目包含三个类文件:Web Part类(包括如何实现WebPartMultiThread
方法和设置超时消息),WebPartMultiThread
定义类,以及WebPartMultiThread
包类。
Web Part类
using System;
using System.Web;
using System.Web.UI;
using System.Threading;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;
public class WorkItemSample :
Microsoft.SharePoint.WebPartPages.WebPart
{
string log = "";
ManualResetEvent mre = new ManualResetEvent(false);
bool threadTimeOut = false;
WebPartMultiThread MultiThread;
public WorkItemSample()
{
}
protected override void OnPreRender(EventArgs e)
{
log += "before register: " +
DateTime.Now.ToLongTimeString() + "<BR>";
MultiThread = new WebPartMultiThread(threadTimeOut, this.Page);
MultiThread.RegisterWorkItemCallback(new WaitCallback(DoWork), null);
//DoWork(null);
log += "after register: " +
DateTime.Now.ToLongTimeString() + "<BR>";
}
protected override void RenderWebPart(HtmlTextWriter output)
{
if (MultiThread != null && MultiThread.ThreadTimeOut)
{
string TimeoutMessage = "Timed out";
MultiThread.RenderWorkItemTimeout(output, TimeoutMessage);
}
else
{
log += "RenderWebPart: " +
DateTime.Now.ToLongTimeString() + "<BR>";
output.Write(log);
}
}
// Sleep for 5 seconds to simulate doing work
private void DoWork(object o)
{
log += "before DoWork: " + DateTime.Now.ToLongTimeString() +
this.Title + "<BR>";
Thread.Sleep(7000);
log += "After DoWork: " + DateTime.Now.ToLongTimeString() +
this.Title + "<BR>";
mre.Set();
}
}
在OnPreRender
期间,我们创建一个新的WebPartMultiThread
类实例,并为其提供一个threadTimeout
来决定何时超时。然后,我们调用RenderWorkItemTimeout
(此方法不是Microsoft.Sharepoint.WebPartPage.WebPart.RenderWorkItemTimeOut
)来开始并行渲染Web Part(假设每个Web Part消耗5秒),以实现性能。在RenderWebPart
期间,我们将根据是否超时来渲染不同的内容。
WebPartMultiThread定义类
using System;
using System.Web;
using System.Web.UI;
using System.Threading;
using System.Xml.Serialization;
public class WebPartMultiThread
{
private bool _threadtimeout;
private Page _page;
public bool ThreadTimeOut
{
set
{
_threadtimeout = value;
}
get
{
return _threadtimeout;
}
}
public System.Web.UI.Page myPage
{
set
{
_page = value;
}
get
{
return _page;
}
}
public WebPartMultiThread(bool pThreadTimeOut, Page pPage)
{
ThreadTimeOut = pThreadTimeOut;
myPage = pPage;
}
public bool RegisterWorkItemCallback(WaitCallback beginCallBack, object state)
{
if (!this.ThreadTimeOut)
{
WebPartMultiThreadPacket pa = new WebPartMultiThreadPacket();
pa.state = state;
pa.beginCallBack = beginCallBack;
PageAsyncTask task = new PageAsyncTask(new BeginEventHandler(
this.OnTaskBeginWithWaitCallback),
new EndEventHandler(this.OnTaskEnd),
new EndEventHandler(this.OnTaskTimeout), pa, true);
if (this.myPage != null)
{
this.myPage.RegisterAsyncTask(task);
}
}
else
return false;
return true;
}
private IAsyncResult OnTaskBeginWithWaitCallback(object sender,
EventArgs e, AsyncCallback cb, object o)
{
return ((WebPartMultiThreadPacket)o).beginCallBack.BeginInvoke(
((WebPartMultiThreadPacket)o).state, cb, null);
}
private void OnTaskEnd(IAsyncResult ar)
{
}
private void OnTaskTimeout(IAsyncResult ar)
{
this.ThreadTimeOut = true;
}
public void RenderWorkItemTimeout(HtmlTextWriter output, string outputMessage)
{
output.Write(outputMessage);
}
}
如何实现OnTaskBeginWithWaitCallback()
是该项目的重要组成部分。它需要一个WebPartMultiThreadPacket
实例。
WebPartMultiThread包类
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Xml.Serialization;
public class WebPartMultiThreadPacket
{
public WaitCallback beginCallBack;
public object state;
public WebPartMultiThreadPacket()
{
}
}
当您运行此页面时,您会看到类似以下截图的内容
历史
这是第一个版本。