C#2010 .Net 4.0的并行运算的源码

// ----------------------------------------------------------------------------------
// Microsoft Developer & Platform Evangelism
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// ----------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
// ----------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Xml.Linq;
using System.Text;
using System.Windows.Forms;
namespace PlinqMvpDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            ProcessorsToUse.Minimum = 1;
            ProcessorsToUse.Maximum = Environment.ProcessorCount;
            ProcessorsToUse.Value = Environment.ProcessorCount; // Use all processors.处理器个数
            LinqYearStartLabel.Text = yearStart.ToString();
            PlinqYearStartLabel.Text = yearStart.ToString();
            LinqYearEndLabel.Text = yearEnd.ToString();
            PlinqYearEndLabel.Text = yearEnd.ToString();
            LinqValueEndLabel.Text = yscaleMax.ToString();
            PlinqValueEndLabel.Text = yscaleMax.ToString();
            InitializeQueries();
            // Eliminate startup costs from the equation.
            System.Threading.ThreadPool.SetMinThreads(Environment.ProcessorCount, Environment.ProcessorCount);
            // Now load 250MB of data by default.
            LoadNames(250);
        }
        private List<PopName> names = new List<PopName>();
        private QueryInfo queryInfo = new QueryInfo();
        private static IEnumerable<PopName> seqQuery;
        private static ParallelQuery<PopName> parQuery;
        const int yearStart = 1960;
        const int yearEnd = 2000;
        const int yscaleMax = 1000;
        class QueryInfo
        {
            internal string Name;
            internal string State;
        }

        private void InitializeQueries()
        {
            seqQuery = from n in names
                       where n.Name.Equals(queryInfo.Name, StringComparison.InvariantCultureIgnoreCase) &&
                             n.State == queryInfo.State &&
                             n.Year >= yearStart && n.Year <= yearEnd
                       orderby n.Year ascending
                       select n;
            parQuery = from n in names.AsParallel().WithDegreeOfParallelism(ProcessorsToUse.Value)
                       where n.Name.Equals(queryInfo.Name, StringComparison.InvariantCultureIgnoreCase) &&
                             n.State == queryInfo.State &&
                             n.Year >= yearStart && n.Year <= yearEnd
                       orderby n.Year ascending
                       select n;
        }

        void LoadNames(float mbSize)
        {
            const int recordSize = 32; // approx. 32 bytes per record.
            int count = (int)((mbSize * 1024 * 1024) / recordSize);
            Cursor oldCursor = Cursor.Current;
            Cursor.Current = Cursors.WaitCursor;
            try
            {
                LinqTimeLabel.Visible = false;
                PlinqTimeLabel.Visible = false;
                SpeedupLabel.Visible = false;
                LastSeqRun = 0;
                LastParRun = 0;
                // Clear the screen.
                LinqPicture.Image = null;
                PlinqPicture.Image = null;
                Refresh();
                names.Clear();
                Console.Write("Loading XML names...");
                XDocument doc = XDocument.Load("popnames.xml");
                XElement root = doc.Root;
                foreach (XElement child in root.Elements())
                {
                    PopName name = new PopName();
                    name.Name = child.Attribute("Name").Value;
                    name.Gender = (NameGender)Enum.Parse(typeof(NameGender), child.Attribute("Gender").Value);
                    name.State = child.Attribute("State").Value;
                    name.Year = int.Parse(child.Attribute("Year").Value);
                    name.Rank = int.Parse(child.Attribute("Rank").Value);
                    name.Count = int.Parse(child.Attribute("Count").Value);
                    names.Add(name);
                    if (names.Count == count) break;
                }
                while (count > names.Count)
                {
                    names.AddRange(names);
                }
                if (names.Count > count)
                {
                    int remCount = names.Count - count;
                    names.RemoveRange(names.Count - remCount - 1, remCount);
                }
                // "Prime" the queries.
                seqQuery.ToList();
                parQuery.ToList();
                //MessageBox.Show(names.Count.ToString());
            }
            finally
            {
                Cursor.Current = oldCursor;
            }
        }
        private const int RunMultiplier = 10;
        private long LastSeqRun = 0;
        private long LastParRun = 0;
        private void DrawResults(List<PopName> names, Graphics g, int width, int height)
        {
            // Clear background to be white.
            g.Clear(Color.Black);
            if (names.Count > 0)
            {
                int maxValue = names.Select((n) => n.Count).Max();
                int minYear = names.Select((n) => n.Year).Min();
                int maxYear = names.Select((n) => n.Year).Max();
                LinqYearStartLabel.Text = minYear.ToString();
                PlinqYearStartLabel.Text = minYear.ToString();
                LinqYearEndLabel.Text = maxYear.ToString();
                PlinqYearEndLabel.Text = maxYear.ToString();
                LinqValueEndLabel.Text = maxValue.ToString();
                PlinqValueEndLabel.Text = maxValue.ToString();
                if (minYear != maxYear)
                {
                    // Note: X axis is years, Y axis is the counts per year.
                    // These are the dimensions everything will be scaled to.
                    float per_x = (float)width / (maxYear - minYear);
                    float per_y = (float)height / maxValue;
                    //MessageBox.Show(String.Format("count = {0}, xscale = {1}, per_x = {2}",
                    //    names.Count.ToString(), xscale_max, per_x));
                    // Draw axis lines:
                    Pen paxis = new Pen(Color.FromArgb(64, 64, 64), 1);
                    for (float i = (height / 10); i < height; i += (height / 10))
                    {
                        g.DrawLine(paxis, 0, i, width, i);
                    }
                    int xvalues = (maxYear - minYear);
                    float xincrement = (float)width / xvalues;
                    for (float i = xincrement; i < width; i += xincrement)
                    {
                        g.DrawLine(paxis, i, 0, i, height);
                    }
                    //g.DrawLine(paxis, 0, 0, width, height);
                    // Draw data:
                    Pen p = new Pen(Color.Chartreuse, 4);
                    float curr_x = 0.0f;
                    float curr_y = 0.0f;
                    float last_x = -1;
                    float last_y = -1;
                    int last_year = -1;
                    foreach (PopName n in names)
                    {
                        if (n.Year != last_year)
                        {
                            if (LineRadioButton.Checked)
                            {
                                curr_x = (maxYear - n.Year) * per_x;
                                curr_y = height - (n.Count * per_y);
                                if (last_x != -1 && last_y != -1)
                                {
                                    g.DrawLine(p, last_x, last_y, curr_x, curr_y);
                                }
                                last_x = curr_x;
                                last_y = curr_y;
                                last_year = n.Year;
                            }
                            else
                            {
                                curr_x = (maxYear - n.Year) * per_x;
                                curr_y = height - (n.Count * per_y);
                                if (last_x != -1 && last_y != -1)
                                {
                                    g.DrawLine(p, curr_x, height, curr_x, curr_y);
                                }
                                last_x = curr_x;
                                last_y = curr_y;
                                last_year = n.Year;
                            }
                        }
                    }
                }
            }
        }
        private void RunLinqButton_Click(object sender, EventArgs e)
        {
            Cursor oldCursor = Cursor.Current;
            Cursor.Current = Cursors.WaitCursor;
            // Set query info values based on text box.
            queryInfo.Name = NameTextBox.Text.Trim();
            queryInfo.State = StateTextBox.Text.Trim();
            try
            {
                // Clear the screen.
                LinqPicture.Image = null;
                Refresh();
                // Execute and time the query:
                List<PopName> names = null;
                Stopwatch sw = new Stopwatch();
                System.Threading.ManualResetEvent mre = new System.Threading.ManualResetEvent(false);
                System.Threading.ThreadPool.QueueUserWorkItem(delegate
                {
                    sw.Start();
                    for (int i = 0; i < RunMultiplier; i++)
                        names = seqQuery.ToList();
                    sw.Stop();
                    LastSeqRun = sw.ElapsedTicks;
                    mre.Set();
                });
                mre.WaitOne();
                // And draw:
                LinqPicture.Image = new Bitmap(LinqPicture.Width, LinqPicture.Height);
                Graphics g = Graphics.FromImage(LinqPicture.Image);
                DrawResults(names, g, LinqPicture.Image.Width, LinqPicture.Image.Height);
                // Note execution time:
                LinqTimeLabel.Text = string.Format("{0:F2} seconds", (sw.ElapsedMilliseconds / 1000.0));
                LinqTimeLabel.Visible = true;
                if (LastSeqRun != 0 && LastParRun != 0)
                {
                    SpeedupLabel.Text = string.Format("{0:F2}x speedup", ((float)LastSeqRun) / LastParRun);
                    SpeedupLabel.Visible = true;
                }
            }
            finally
            {
                Cursor.Current = oldCursor;
            }
        }
        private void RunPlinqButton_Click(object sender, EventArgs e)
        {
            Cursor oldCursor = Cursor.Current;
            Cursor.Current = Cursors.WaitCursor;
            // Set query info values based on text box.
            queryInfo.Name = NameTextBox.Text.Trim();
            queryInfo.State = StateTextBox.Text.Trim();
            try
            {
                // Clear the screen.
                PlinqPicture.Image = null;
                Refresh();
                // Execute and time the query:
                List<PopName> names = null;
                Stopwatch sw = new Stopwatch();
                System.Threading.ManualResetEvent mre = new System.Threading.ManualResetEvent(false);
                System.Threading.ThreadPool.QueueUserWorkItem(delegate
                {
                    sw.Start();
                    for (int i = 0; i < RunMultiplier; i++)
                        names = parQuery.ToList();
                    sw.Stop();
                    LastParRun = sw.ElapsedTicks;
                    mre.Set();
                });
                mre.WaitOne();
                // And draw:
                PlinqPicture.Image = new Bitmap(PlinqPicture.Width, PlinqPicture.Height);
                Graphics g = Graphics.FromImage(PlinqPicture.Image);
                DrawResults(names, g, PlinqPicture.Image.Width, PlinqPicture.Image.Height);
                // Note execution time:
                PlinqTimeLabel.Text = string.Format("{0:F2} seconds", (sw.ElapsedMilliseconds / 1000.0));
                PlinqTimeLabel.Visible = true;
                if (LastSeqRun != 0 && LastParRun != 0)
                {
                    SpeedupLabel.Text = string.Format("{0:F2}x speedup", ((float)LastSeqRun) / LastParRun);
                    SpeedupLabel.Visible = true;
                }
            }
            finally
            {
                Cursor.Current = oldCursor;
            }
        }
        private void InputSize1MB_CheckedChanged(object sender, EventArgs e)
        {
            if (((RadioButton)sender).Checked)
                LoadNames(1);
        }
        private void InputSize5MB_CheckedChanged(object sender, EventArgs e)
        {
            if (((RadioButton)sender).Checked)
                LoadNames(5);
        }
        private void InputSize10MB_CheckedChanged(object sender, EventArgs e)
        {
            if (((RadioButton)sender).Checked)
                LoadNames(10);
        }
        private void InputSize50MB_CheckedChanged(object sender, EventArgs e)
        {
            if (((RadioButton)sender).Checked)
                LoadNames(50);
        }
        private void InputSize100MB_CheckedChanged(object sender, EventArgs e)
        {
            if (((RadioButton)sender).Checked)
                LoadNames(100);
        }
        private void InputSize250MB_CheckedChanged(object sender, EventArgs e)
        {
            if (((RadioButton)sender).Checked)
                LoadNames(250);
        }
        private void InputSize500MB_CheckedChanged(object sender, EventArgs e)
        {
            if (((RadioButton)sender).Checked)
                LoadNames(500);
        }
        private void InputSize1GB_CheckedChanged(object sender, EventArgs e)
        {
            if (((RadioButton)sender).Checked)
                LoadNames(1000);
        }
        private void ProcessorsToUse_Scroll(object sender, EventArgs e)
        {
            InitializeQueries();
        }
 
        enum NameGender { Male, Female }
        class PopName
        {
            // Fields:
            private string m_name;
            private NameGender m_gender;
            private string m_state;
            private int m_year;
            private int m_rank;
            private int m_count;
            // Properties:
            internal string Name { get { return m_name; } set { m_name = value; } }
            internal NameGender Gender { get { return m_gender; } set { m_gender = value; } }
            internal string State { get { return m_state; } set { m_state = value; } }
            internal int Year { get { return m_year; } set { m_year = value; } }
            internal int Rank { get { return m_rank; } set { m_rank = value; } }
            internal int Count { get { return m_count; } set { m_count = value; } }
            public override string ToString()
            {
                return string.Format("{{ Name={0}, Gender={1}, State={2}, Year={3}, Rank={4}, Count={5} }}",
                    Name, Gender, State, Year, Rank, Count);
            }
        }
    }
}

你可能感兴趣的:(源码,运算,职场,net,休闲)