5,445,109 members and growing! (14,695 online)
Email Password   helpLost your password?
Enterprise Systems » SharePoint Server » Web Parts     Intermediate License: The Code Project Open License (CPOL)

Multithread in MOSS page by implementing PageAsyncTask

By David Meng

To implement PageAsyncTask for web part rendering in parallel instead of RegisterWorkItem.
C# (C# 1.0, C# 2.0, C# 3.0, C#), Office, ASP.NET, Dev

Posted: 24 Apr 2008
Updated: 24 Apr 2008
Views: 3,392
Bookmarked: 6 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
3 votes for this Article.
Popularity: 2.27 Rating: 4.75 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
0 votes, 0.0%
3
1 vote, 33.3%
4
2 votes, 66.7%
5

Introduction

Currently, more and more companies are beginning to move to SharePoint 2007. As the basis of SharePoint applications, web parts need more attention since they are customized to business or user requirements. Let’s discuss some issues about how to upgrade an async web part from SharePoint 2003 to SharePoint 2007.

Background

When developers recompile a web part which implements multiple threads rendered using Microsoft.SharePoint.WebPartPages.WebPart.RegisterWorkItem, they would find a warning: 'Microsoft.SharePoint.WebPartPages.WebPart.RegisterWorkItemCallback(System.Threading.WaitCallback, object)' is obsolete: 'Use Page.RegisterAsyncTask instead.'.

It’s easy to implement Page.RegisterAsyncTask, just like MSDN says. The challenge is how to make it work in the SharePoint web part page…

First, let's walk through the source code

The project contains three class files: the web part class (including how to implement the WebPartMultiThread method and set time out messages), the WebPartMultiThread definition class, and the WebPartMultiThread package class.

The web part class

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();
    }
}

During OnPreRender, we create a new instance of our WebPartMultiThread class and give it a threadTimeout to decide when the time expires. Then, we invoke RenderWorkItemTimeout (this method is not Microsoft.Sharepoint.WebPartPage.WebPart.RenderWorkItemTimeOut) to start rendering the web part (supposed to consume 5 seconds per web part) in parallel to achieving the performance. During RenderWebPart, we will render different contents depending on whether it was expired or not.

The WebPartMultiThread definition class

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);
    }
}

How to implement OnTaskBeginWithWaitCallback() is an important part of this project. It needs an instance of WebPartMultiThreadPacket.

The WebPartMultiThread package class

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()
    {
    }
}

When you run this page, you see something like this screenshot:

History

This is the first version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

David Meng


I am so happy to have the opportunity to share experience each other with you. Currently I am a web developer on sharepoint solutions. In this field I have developed many web parts for Toronto based organizations. Recently I have done one portal customization and upgrade it from WSS 2.0 to WSS3.0. I like sharepoint development. It brings me to the world of the collision between cutting edge techniques and traditional ways. I am enjoying the experience to know Microsoft wisdoms.
Occupation: Web Developer
Company: MapleCity Consulting Inc.
Location: Canada Canada

Other popular SharePoint Server articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
  (Refresh) 
Subject  Author Date 
-- There are no messages in this forum --

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 24 Apr 2008
Editor: Smitha Vijayan
Copyright 2008 by David Meng
Everything else Copyright © CodeProject, 1999-2008
Web11 | Advertise on the Code Project