The following piece of code will keep a specified number of threads running concurrently. The threads all execute the same method which could be any kind of "worker process".

The reason for this was performance issues on both multiple CPU's and CPU's with hyperthreading. From my tests, a dual-CPU server would run most efficiently when 4 threads were running concurrently. The processing speed would be 3 times faster than when running 1 thread.

                Thread[] Threads = new Thread[THREAD_COUNT];

                int RunningThreads = 1;
                int IdleThreadIdx = 0;

                while (RunningThreads > 0)
                {
                    // Start a new thread while an idle thread slot is available
                    if ((IdleThreadIdx < THREAD_COUNT) && (!_Stopping))
                    {
                        // It is assumed that this thread will terminate within 1000ms if it has no work to do.
                        Threads[IdleThreadIdx] = new Thread(new ThreadStart(ProcessEvents));
                        Threads[IdleThreadIdx].Start();
                    }
                    Thread.Sleep(1000);

                    // Search for the first idle thread, and check number of idle threads:
                    IdleThreadIdx = int.MaxValue;
                    RunningThreads = 0;

                    for (int i = THREAD_COUNT - 1; i >= 0; i--)
                    {
                        if ((ThreadsIdea != null) && (ThreadsIdea.IsAlive))
                        {
                            RunningThreads++;
                        }
                        else
                        {
                            IdleThreadIdx = i;
                        }
                    }
                }

 Note that the worker method "ProcessThreads" must not throw an exception, otherwise it seems that the calling application (in my case a Windows service) will be terminated without an exception.

I posted this article on a simple way to improve performance in ASP .net applications using Paladin.

Please feel free to comment or give some further ideas on the topic.

http://community.sgdotnet.org/blogs/hannes/articles/19159.aspx

I just made the leap from Paladin RC1 to RC3.

The biggest change in code for me is the usage of FilterList's, but I agree with the change.

I use filters everywhere, but most often as a singular equals comparison. For this reason I created this class to save some typing.  Just note that logical AND is used between filters for this class.

public class FilterListEqual : FilterList
{
   
public FilterListEqual(string fieldname, object equalvalue)
      : base(new Filter(fieldname, Comparison.Equals, equalvalue)) {}

   public Filter Add(string fieldname, object equalvalue)
   {
      if (this.Count == 0)
      {
         return base.Add(fieldname, Comparison.Equals, equalvalue);
      }
      else
      {
         return base.Add(Logical.And, fieldname, Comparison.Equals, equalvalue);
      }
   }
}

Yep, that's it. The usage for a single equals comparison would then be:

BusinessComponent BC = new BusinessComponent;
BC.Populate(BudgetList, new FilterListEqual(epcdb.Budget.FieldNames.name, "Budget 2005"));

The overloaded Add method can be used to add more filters, or you could create more overloaded constructors.

This is one way to check for duplicates when adding/editing records with unique field values.  It is useful when the list to check against is not available locally, ie. when the database must be checked for duplicates.

A CustomValidator's ServerValidate event is used here.  EditID is the primary key of the record being edited, or 0 if a new record is added.  The "name" field is checked for uniqueness.

// Paladin RC2 code - pass a FilterList to BC.Populate for RC3!
private void valName_ServerValidate(object source, System.Web.UI.WebControls.ServerValidateEventArgs args)
{
try
{
   string new_name = args.Value.ToString();
   db.ProductList ProductList = new db.ProductList();
   ProductList.Filters.Add(db.Product.FieldNames.name, Comparison.Equals, new_name);
   if (EditID != 0)
   {
      ProductList.Filters.Add(Logical.And, db.Product.FieldNames.id, Comparison.NotEquals, EditID);
   }   

   BusinessComponent BC = new BusinessComponent();
   BC.Populate(ProductList);
   args.IsValid = (ProductList.Count == 0);
}
catch (Exception ex)
{
   args.IsValid = false;
   // display error
}
}

Note: If a complete entity list is available, you would rather use the following check to avoid the trip to the server:

int idx = CompleteProductList.Find(db.Product.FieldNames.name, new_name);
IsValid = ( (idx < 0) ||   ((CompleteProductList[idx].id == EditID) );

Let me know about other ways to check for duplicates!

I built this silly control for Ok/Cancel Javascript prompts initiated from the server side. This is useful in cases where you would like to check whether you do want the prompt to pop up first, eg. to check whether the user is allowed to delete an item or not.

To use the control, the Show method is called, and the Click event will fire if the user clicks Ok.

The source code is small enough. :)

[ Designer("epc_webcontrols.popupDesigner, epc_webcontrols") ]
public class popup : WebControl
{
  public event EventHandler Click;
  private LinkButton _Button;

  private string FmtJSConstant(string s)
  { return s.Replace("\\", "\\\\").Replace("'", "\\'"); }

  public void Show(string prompt)
  {
    string JID = this.UniqueID.Replace(":", "_");
    string script =
      "<script>" +
      " if(confirm('%%TEXT%%')) __doPostBack('%%CID%%','');" +
      "</script>";
    script = script.Replace("%%JID%%", JID);
    script = script.Replace("%%TEXT%%", FmtJSConstant(prompt));
    script = script.Replace("%%CID%%", FmtJSConstant(_Button.ClientID));
    if (!Page.IsClientScriptBlockRegistered("pppopup_" + JID))
      Page.RegisterStartupScript("pppopup_" + JID, script);
  }

  protected override void OnInit(EventArgs e)
  {
    _Button = new LinkButton();
    this.Controls.Add(_Button);
    _Button.Click += new EventHandler(_Button_Click);
    base.OnInit (e);
  }

  private void _Button_Click(object sender, EventArgs e)
  {
    if (Click != null) Click(this, e);
  }
 }

 public class popupDesigner : System.Web.UI.Design.ControlDesigner
 {
   public override string GetDesignTimeHtml()
   {
     popup ctl = (popup) Component;
     return @"<DIV style='background-color:blue;color:white;'>Ok / Cancel</DIV>";
   }
}

I posted an article - more of a brief source code explanation - of an updown control that I use in my web projects.

http://community.sgdotnet.org/blogs/hannes/articles/18061.aspx

The control allows the user to enter numeric values or scroll the value using up/down buttons, and enforces valid values. 

The source code for the control is available at the following url.

http://triplez.sg.gs/sgdotnet/Updown.zip

I will check these issues on Windows XP when possible, and post any remaining issues to the Paladin Knowledge Base. For now, it is only useful to developers working on Windows 2000, which I guess is me.

Error: Failed to register assembly 'Paladin.Core, Version=0.9....

Resolution:
The COM+ application can not register automatically for some reason.
Execute regsvcs Paladin.Core.dll and do the same for all assemblies that take part in COM+ transactions.
The assemblies will also need to have strong names (signed with a key).
Signing is not possible for the web application assembly, so all business components should be moved to another assembly.
Whenever an assembly's COM+ components are modified, the COM+ application should be registered again.

Error: An error occurred while enlisting in a distributed transaction.

Resolution:
This could happen when the assembly that you are creating the object from does not have a strong name - an issue if you would like to use ServicedBusinessComponent in your web application.

I attempted to solve this issue by changing the Paladin Enterprise Services COM+ application's activation type to server application. This in turn produces an Access is denied error. The system event log reports that this is because an IUSR_ account is used to attempt launching a DCOM Server. I did not attempt to resolve this security issue, and abandoned this approach.

To work around this issue, you can create a replacement class in a signed assembly. Any class that inherits from ServicedBusinessBase will do. This wrapper class can then be used within the web application without problems.

I just copied this from my blogger account to test things out. :)

For some reason I have never used the table-layout CSS2 attribute. It is handy in cases where one column should use all "remaining width" of a table.

With table-layout set to auto (the default), the table below will have its first two columns condensed.
<table width="100%"><tr>
<td width="100" bgcolor="Red">a</td>
<td width="200" bgcolor="Blue">b</td>
<td width="100%" bgcolor="Green">c</td>
</tr></table>

a b c

With table-layout set to fixed, 100% can be regarded as "all remaining space". The <col> notation is optional, but I prefer it.
<table width="100%" style="table-layout: fixed"><tr>
<col width="100"><col width="200"><col width="100%">
<td bgcolor="Red">a</td>
<td bgcolor="Blue">b</td>
<td bgcolor="Green">c</td>
</tr></table>

a b c

The second Red/Blue/Green table is often the desired result. There must be other ways to get the same results and I would like to hear about them.

I did have a working layout without using fixed tables, but it caused the horizontal scrollbar to appear in IE6 at the incorrect width.