The WaitForAll Roadshow

Posted by adweigert on ASP.net Weblogs See other posts from ASP.net Weblogs or by adweigert
Published on Wed, 26 May 2010 12:41:00 GMT Indexed on 2010/05/26 12:51 UTC
Read the original article Hit count: 389

Filed under:
|
|
|
|

OK, so I took for granted some imaginative uses of WaitForAll but lacking that, here is how I am using. First, I have a nice little class called Parallel that allows me to spin together a list of tasks (actions) and then use WaitForAll, so here it is, WaitForAll's 15 minutes of fame ...

First Parallel that allows me to spin together several Action delegates to execute, well in parallel.

 

public static class Parallel
{
    public static ParallelQuery Task(Action action)
    {
        return new Action[] { action }.AsParallel();
    }

    public static ParallelQuery> Task(Action action)
    {
        return new Action[] { action }.AsParallel();
    }

    public static ParallelQuery Task(this ParallelQuery actions, Action action)
    {
        var list = new List(actions);
        list.Add(action);
        return list.AsParallel();
    }

    public static ParallelQuery> Task(this ParallelQuery> actions, Action action)
    {
        var list = new List>(actions);
        list.Add(action);
        return list.AsParallel();
    }
}

 

Next, this is an example usage from an app I'm working on that just is rendering some basic computer information via WMI and performance counters. The WMI calls can be expensive given the distance and link speed of some of the computers it will be trying to communicate with. This is the actual MVC action from my controller to return the data for an individual computer.

 

public PartialViewResult Detail(string computerName)
{
    var computer = this.Computers.Get(computerName);
    var perf = Factory.GetInstance();

    var detail = new ComputerDetailViewModel()
        {
            Computer = computer
        };

    try
    {
        var work = Parallel
            .Task(delegate 
            {
                // Win32_ComputerSystem
                var key = computer.Name + "_Win32_ComputerSystem";
                var system = this.Cache.Get(key);

                if (system == null)
                {
                    using (var impersonation = computer.ImpersonateElevatedIdentity())
                    {
                        system = computer.GetWmiContext().GetInstances().Single();
                    }

                    this.Cache.Set(key, system);
                }

                detail.TotalMemory = system.TotalPhysicalMemory;
                detail.Manufacturer = system.Manufacturer;
                detail.Model = system.Model;
                detail.NumberOfProcessors = system.NumberOfProcessors;
            })
            .Task(delegate 
            {
                // Win32_OperatingSystem
                var key = computer.Name + "_Win32_OperatingSystem";
                var os = this.Cache.Get(key);

                if (os == null)
                {
                    using (var impersonation = computer.ImpersonateElevatedIdentity())
                    {
                        os = computer.GetWmiContext().GetInstances().Single();
                    }

                    this.Cache.Set(key, os);
                }

                detail.OperatingSystem = os.Caption;
                detail.OSVersion = os.Version;
            })
            // Performance Counters
            .Task(delegate 
            {
                using (var impersonation = computer.ImpersonateElevatedIdentity())
                {
                    detail.AvailableBytes = perf.GetSample(computer, "Memory", "Available Bytes");
                }
            })
            .Task(delegate 
            {
                using (var impersonation = computer.ImpersonateElevatedIdentity())
                {
                    detail.TotalProcessorUtilization = perf.GetValue(computer, "Processor", "% Processor Time", "_Total");
                }
            }).WithExecutionMode(ParallelExecutionMode.ForceParallelism);

        if (!work.WaitForAll(TimeSpan.FromSeconds(15), task => task()))
        {
            return PartialView("Timeout");
        }
    }
    catch (Exception ex)
    {
        this.LogException(ex);
        return PartialView("Error.ascx");
    }

    return PartialView(detail);
}

© ASP.net Weblogs or respective owner

Related posts about c#

Related posts about LINQ