Amazon.com Widgets VB

WilliaBlog.Net

I dream in code

About the author

Robert Williams is an internet application developer for the Salem Web Network.
E-mail me Send mail
Code Project Associate Logo
Go Daddy Deal of the Week: 30% off your order at GoDaddy.com! Offer expires 11/6/12

Recent comments

Archive

Authors

Tags

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.


Use lambda expressions to aggregate values into a delimited string

Let's say you need to aggregate one value from each object in a list into a single string. For Example, you want to send an e-mail to a set of customers. This requires a string with the email addresses seperated by a semicolon (;). The following code will create a generic List of Books, and provide a method ListAllEmails() that will print the delimited list of emails to the console window:

 

namespace ConsoleApplication1

{

    using System;

    using System.Collections.Generic;

    using System.Linq;

 

    public class Lambdas

    {

        /// <summary>

        /// Define the Book Class

        /// </summary>

        public class Book

        {

            public string Title { get; set; }

            public string Author { get; set; }

            public double Price { get; set; }

            public string EmailAddress { get; set; }

        }

 

        public List<Book> Books { get; private set; }

 

        public Lambdas()

        {

            // Create a new list of Books

            Books = new List<Book> {

                new Book { Title = "Pro ASP.Net MVC Framework", Author = "Steven Sanderson", Price = 49.99, EmailAddress = "steve@nospam.com" },

                new Book{ Title = "Pro Silverlight 2 in C# 2008", Author = "Matthew MacDonald", Price = 49.99, EmailAddress = "Matthew@nospam.com" },

                new Book{ Title = "Pro VB 2008 and the .Net 3.5 Platform", Author = "Andrew Troelsen", Price = 59.99, EmailAddress = "Andrew@nospam.com" }

            };

        }

 

        /// <summary>

        /// Creates a semicolon (;) delimited list of email addresses

        /// </summary>

        public void ListAllEmails()

        {

            Console.WriteLine(this.Books.Select(b => b.EmailAddress).Aggregate((items, item) => items + "; " + item));

            // output= "steve@nospam.com; Matthew@nospam.com; Andrew@nospam.com"

        }

    }

}

 

The Select Method selects the EmailAddress for each Book. The Aggregate method builds a list of the items based on the lambda expression. Notice that this did not require any additional code to ensure there is no extra semi-colon at the beginning or end of the list, which is often required when using a loop to concatenate text.

 

Note: Be careful when using the Aggregate method because it is very inefficient on large numbers of strings. Consider using the String Join method instead.

 

In VB, the lambda would look like this:

 

   Console.WriteLine(Books.Select(Function(b) b.EmailAddress).Aggregate(Function(items, item) items & "; " & item))

 

You can also filter the list of email addresses. For Example, suppose you want to send an email to all the authors who sell their books for under $50, telling them that you think you can sell their next book for $59.99:

 

        /// <summary>

        /// Creates a semicolon (;) delimited list of email addresses where the price of the book is under $50

        /// </summary>

        public void ListSomeEmails()

        {

            Console.WriteLine(this.Books.Where(b => b.Price < 50).Select(b => b.EmailAddress).Aggregate((items, item) => items + ", " + item));

            // output= "steve@nospam.com, Matthew@nospam.com"

        }

 

Let's take this one step further. Suppose you wanted to create a comma separated list of values and replace the last comma with " and", so that a single item would be "item1", two items would be "item1 and item2", three items would be "item1, item2 and item3", etc.

 

        /// <summary>

        /// Creates a comma delimited list of email addresses and replaces the last comma with " and "

        /// </summary>

        public void ListEmailsAsSmartCsv()

        {

            string csv = this.Books.Select(b => b.EmailAddress).Aggregate((items, item) => items + ", " + item);

            Console.WriteLine(Regex.Replace(csv, @",\s([^,]+)$", " and $1"));

            // output= "steve@nospam.com, Matthew@nospam.com and Andrew@nospam.com"

        }

 

 


Tags:
Categories: ASP.Net | C# | VB
Posted by Williarob on Friday, February 26, 2010 9:44 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Simplify Your Code with Lambda Expressions

Most applications retain lists of things, and a common task is to find an item in that list. The following class illustrates three ways to find an item in a generic list:

 

namespace ConsoleApplication1

{

    using System;

    using System.Collections.Generic;

    using System.Linq;

 

    public class Lambdas

    {

        public class Book

        {

            public string Title { get; set; }

            public string Author { get; set; }

            public double Price { get; set; }

        }

 

        public List<Book> Books { get; private set; }

 

        public Lambdas()

        {

            Books = new List<Book> {

                new Book { Title = "Pro ASP.Net MVC Framework", Author = "Steven Sanderson", Price = 49.99 },

                new Book{ Title = "Pro Silverlight 2 in C# 2008", Author = "Matthew MacDonald", Price = 49.99},

                new Book{ Title = "Pro VB 2008 and the .Net 3.5 Platform", Author = "Andrew Troelsen", Price = 59.99 }

            };

        }

 

        /// <summary>

        /// Returns a book using a traditional loop

        /// </summary>

        private Book FindUsingTraditionalLoop(string title)

        {

            Book foundBook = null;

 

            foreach (var b in this.Books)

            {

                if (b.Title == title)

                {

                    foundBook = b;

                    break;

                }

            }

 

            return foundBook;

        }

 

        /// <summary>

        /// Returns the book using a Linq expression

        /// </summary>

        private Book FindUsingLinq(string title)

        {

            var query = from b in this.Books

                        where b.Title == title

                        select b;

 

            return query.Count() > 0 ? query.ToList()[0] : null;

        }

 

        /// <summary>

        /// Returns the book using a Lambda expression

        /// </summary>

        private Book FindUsingLambda(string title)

        {

            return this.Books.FirstOrDefault(b => b.Title == title);

        }

 

        public void Test()

        {

            Console.WriteLine("Found: {0}", this.FindUsingTraditionalLoop("Pro Silverlight 2 in C# 2008").Author);

            Console.WriteLine("Found: {0}", this.FindUsingLinq("Pro Silverlight 2 in C# 2008").Author);

            Console.WriteLine("Found: {0}", this.FindUsingLambda("Pro Silverlight 2 in C# 2008").Author);

        }

    }

}

As these examples show, you can save time reading and writing your code by using Lambda expressions to find items in a list.

For VB programmers, the syntax of the Lambda expression looks like this:

return Me.Books.FirstOrDefault(Function(b) b.Title = title)


Categories: ASP.Net | C# | VB
Posted by Williarob on Wednesday, January 06, 2010 8:10 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Delayed Automatic Exit from Console Application v2.0

This is an alternate version to the one originally posted here. It occurred to me that if someone was actually at the console and the program quit without warning, while allegedly waiting for a key press, that would be a bit surprising and/or annoying. This new version displays a warning with an on screen count down leading up to the automatic exit:

 

    1 using System;

    2 using System.Threading;

    3 

    4 namespace ConsoleApplication1

    5 {

    6     class Program

    7     {

    8         static void Main(string[] args)

    9         {

   10             //... code here for whatever your console app does

   11             Console.WriteLine("[Result of the Program]" + Environment.NewLine);

   12 

   13             Console.WriteLine("...press any key to exit." + Environment.NewLine);

   14 

   15             delay = new ExitDelay();

   16             delay.Start();

   17             MyTimer = new Timer(TimesUp, null, 1000, 1000);

   18         }

   19 

   20         static ExitDelay delay;

   21         static Timer MyTimer;

   22         static int CountDown = 10;

   23 

   24         // Timer callback: they didn't press any key, but we don't want this window open forever!

   25         private static void TimesUp(object state)

   26         {

   27             if(CountDown > 0)

   28             {

   29                 Console.CursorLeft = 0;

   30                 Console.Write("Program will exit automatically in " + CountDown + " ");

   31                 CountDown--;

   32             }

   33             else

   34             {

   35                 Console.CursorLeft = 0;

   36                 Console.WriteLine("Exiting - Bye!                                   ");

   37                 Thread.Sleep(1000);

   38                 delay.Stop();

   39                 MyTimer.Dispose();

   40                 Environment.Exit(0);

   41             }

   42         }

   43 

   44     }

   45 

   46     public class ExitDelay

   47     {

   48         private readonly Thread workerThread;

   49 

   50         public ExitDelay()

   51         {

   52             this.workerThread = new Thread(this.work);

   53             this.workerThread.Priority = ThreadPriority.Lowest;

   54             this.workerThread.Name = "ExitTimer";

   55         }

   56 

   57         public void Start()

   58         {

   59             this.workerThread.Start();

   60         }

   61 

   62         public void Stop()

   63         {

   64             this.workerThread.Abort();

   65         }

   66 

   67         private void work()

   68         {

   69             Console.ReadKey();

   70             this.Stop();

   71         }

   72     }

   73 

   74 }

 


Categories: VB
Posted by Williarob on Saturday, December 13, 2008 12:08 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Traditional Console Spinner

Add this class to your console application, to assure the users that long running tasks are still working.

 

    1 Imports System.Threading

    2 

    3 Public Class ConsoleSpinner

    4     ' Methods

    5     Public Sub New(ByVal ProcessingMsg As String, ByVal FinishedMessage As String)

    6         Me.processingMessage = ProcessingMsg

    7         Me.finishedMessage = FinishedMessage

    8         Me.workerThread = New Thread(New ThreadStart(AddressOf Me.Spin))

    9         Me.workerThread.Priority = ThreadPriority.Lowest

   10         Me.workerThread.Name = "ConsoleSpinner"

   11     End Sub

   12 

   13     Private Sub Spin()

   14         Dim index As Integer = 0

   15         Do While (1 <> 0)

   16             Console.Write(ChrW(13) & "{0} {1}", Me.processingMessage, ConsoleSpinner.anim(index))

   17             index += 1

   18             If (index >= ConsoleSpinner.anim.Length) Then

   19                 index = 0

   20             End If

   21             Thread.Sleep(100)

   22         Loop

   23     End Sub

   24 

   25     Public Sub Start()

   26         Me.workerThread.Start()

   27     End Sub

   28 

   29     Public Sub [Stop]()

   30         Me.workerThread.Abort()

   31         Console.WriteLine("")

   32         Console.WriteLine(Me.finishedMessage)

   33     End Sub

   34 

   35 

   36     ' Fields

   37     Private Shared anim As String() = New String() {"|", "/", "-", "\", "|", "/", "-", "\"}

   38     Private finishedMessage As String

   39     Public processingMessage As String = String.Empty

   40     Private workerThread As Thread

   41 End Class

Call it from any point in your main program using:

   Dim cs As New ConsoleSpinner("Working...", "Done.")

   cs.Start()
  

   ' Do Something that may take a while...

 

   cs.Stop()

 


Categories: VB
Posted by Williarob on Saturday, December 13, 2008 7:10 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Page Load Event Fires Twice

If you have set a breakpoint in the page_load event of your web form and have found it fires twice, view source on the page and check for anything that uses a src="" attribute that is either empty or contains number sign (src="#"). If you find one, make sure you set it to something, if it is an image find a spacer.gif or something you can use, if it is a script or an Iframe either set it or remove it. If you think about it this makes perfect sense, an image tag with an empty src attribute will end up calling the page as the source, which will fire the page load event again. In my case, I was using an <asp:image> tag that had no imageurl until the submit button was pushed and a green check mark or red cross was assigned to it as part of an onscreen Success/Failure message. Making it default to the check mark image resolved my issue. While researching this I found these other possible causes:

  • Check to see if AutoEventWireUp is set to false in the page/control directive.
  • If you are using Visual Basic, check to see that your Handles keyword is only handling one event:"Handles MyBase.Load, Me.Load" would cause it to fire twice.
  • If it only happens on postback, check that your Javascript form validation does not end with form.submit() which would effectively submit your form twice.

Categories: ASP.Net | C# | VB
Posted by Williarob on Thursday, July 24, 2008 1:23 PM
Permalink | Comments (3) | Post RSSRSS comment feed

Process and Thread Basics

Programs, Processes and Threads

In .NET terms, a program can be defined as an assembly, or group of assemblies, that work together to accomplish a task. Assemblies are little more than a way of packaging instructions into maintainable elements and are generally compiled into a dynamic link library (DLL) or an executable (EXE), or a combination of the two.

A process gives a program a place to run, allowing access to memory and resources. Generally, each process runs relatively independent of other processes. In particular, the memory where your program variables will reside is completely separate from the memory used by other processes. Your email program cannot directly assign a new value to a variable in the web browser program. If your email program can communicate with your web browser—for instance, to have it open a web page from a link you received in email—it does so with some form of communication that takes much more time than a memory access.

By putting programs into processes and using only a restricted, mutually agreed-upon communication between them has a number of advantages. One of the advantages is that an error in one process will be less likely to interfere with other processes. Before multitasking operating systems, it was much more common for a single program to be able to crash the entire machine. Putting tasks into processes, and limiting interaction with other processes and the operating system, has greatly added to system stability.

All modern operating systems support the subdivision of processes into multiple threads of execution. Threads run independently, like processes, and no thread knows what other threads are running or where they are in the program unless they synchronize explicitly. The key difference between threads and processes is that the threads within a process share all the data of the process. Thus, a simple memory access can accomplish the task of setting a variable in another thread. Every program will have at least one thread.

In his book ".NET Multithreading" Alan Dennis compares a Process to a house and a thread to a housecat. He writes:

The cat spends most of its time sleeping, but occasionally it wakes up and performs some action, such as eating. The house shares many characteristics with a process. It contains resources available to beings in it, such as a litter box. These resources are available to things within the house, but generally not to things outside the house. Things in the house are protected from things outside of the house. This level of isolation helps protect resources from misuse. One house can easily be differentiated from another by examining its address. Most important, houses contain things, such as furniture, litter boxes, and cats.

Cats perform actions. A cat interacts with elements in its environment, like the house it lives in. A housecat generally has a name. This helps identify it from other cats that might share the same household. It has access to some or the entire house depending on its owner’s permission. A thread’s access to elements may also be restricted based on permissions, in this case, the system’s security settings.

Multitasking

Multitasking means that more than one program can be active at a time. You may take it for granted that you can have an email program and a web browser program running at the same time. Yet, not that long ago, this was not the case. In the days of DOS you would need to save and close your spreadsheet before opening your word processor. With the advent of Windows, you could open multiple applications at once. Windows 3.x used something called Cooperative Multitasking which is based on the assumption that all running processes will yield control to the operating system at a frequent interval. The problem with this model was that not all software developers followed these rules and a program that did not return control to the system, or did so very infrequently, could destabilize the operating system, causing it to "lock up". When Windows 3.x started a new application, that application was invoked from the main thread. Windows passed control to the application with the understanding that control would quickly be returned to windows. If that didn't happen, all other running applications including the operating system could no longer execute instructions. Today, Windows employs Preemptive Multitasking. In this model, instead of relying on programs to return control to the system at regular intervals, the OS simply takes it. 

The main thread of a typical windows program executes a loop (Called a message pump). The loop checks a message queue to see if there is work to do and if there is, it does the work. For example, when a user clicks on a button in a windows application the click event adds work to the message queue indicating which method should be executed. This method is of course known as an event handler. While the loop is executing an event handler, it cannot process additional messages. Multithreading (literally using more than one thread) is how we can work around this limitation. Instead of having the main thread that was assigned to this program do the time consuming work, we assign the work to a seperate thread and have it do the work.

There are a number of ways to create and manage these new threads - using System.Threading, creating a delegate method, implementing the Event Based Asynchronous Pattern, using waithandles, etc. and I intend to explore all of them future articles. In a single core processor, this execution on a separate thread would be periodically interrupted by the operating system to allow other threads a chance to get work done; but after decades in a world where most computers had only one central processing unit (CPU), we are now in a world where only "old" computers have one CPU. Multi-core processors are now the norm. Therefore, every software developer needs to Think Parallel.

Multithreading

Multithreading allows a process to overlap I/O and computation. One thread can execute while another thread is waiting for an I/O operation to complete. Multithreading makes a GUI (graphical user interface) more responsive. The thread that handles GUI events, such as mouse clicks and button presses, can create additional threads to perform long-running tasks in response to the events. This allows the event handler thread to respond to more GUI events. Multithreading can speed up performance through parallelism. A program that makes full use of two processors may run in close to half the time. However, this level of speedup usually cannot be obtained, due to the communication overhead required for coordinating the threads.


Posted by Williarob on Saturday, June 28, 2008 9:00 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Asynchronous DataSet

If you haven't yet read the article "Scalable Apps with Asynchronous Programming in ASP.NET" by Jeff Prosise or seen his presentation at TechEd then you should cetainly take the time to do so, however I'll summarize the key points briefly here. Basically, there is a finite number of Threads available to ASP.Net for request handling, and by making database calls the way that most textbooks and articles recommend, many of the available threads that should be handling requests are actually tapping their feet waiting for your database request to complete, before it can serve your page and return to the thread pool. When all the threads are busy, incoming requests are queued, and if that queue becomes too long then users start to see HTTP 503 Service unavailable errors. In other words there is a glass ceiling to scalability, with synchronous IO requests in asp.net.

 To make optimum use of the thread pool all IO requests that you know could take a second or more to process should be made asynchronously and the links above will give you plenty of examples of how you should do this. The purpose of this article is to demonstrate how you can return a DataSet asynchronously, which is not something I could find an example of anywhere. Another thing I could not find in my research was how to use asynchronous database calls when you have a datalayer, as opposed to a page or usercontrol that contacts the database directly, and I will provide you with both here.

If you have looked at examples of asynchronous database calls elsewhere on the web before arriving here you have probably become familair with the BeginExecuteReader and EndExecuteReader methods of the SQLClient namespace, but where is the BeginExecuteDataSet method? If you need a dataset, why should that have to be a synchronous request? I could not find any asynchronous methods for the DataAdapter and while I did find ways to call a WebMethod or WebService that returns a dataset asynchronously, why should you have to break your methods that return datasets out to webservices? I also found some examples of how to create delegates or use System.Threading.Thread.Start to create datasets in their own thread, but, according to Mr. Prosise these are worthless in ASP.Net because both of these methods actually steal threads for the same thread pool ASP.Net is using anyway! So by using System.Threading.Thread.Start to create your dataset all you are doing is returning a thread to the threadpool and immediately grabbing another one. So how can you do it?

For this example I borrowed the Datalayer from the Job Site Starter Kit and added some Asynchronous methods to it. Here is my BeginExecuteDataSet method:

       Public Function BeginExecuteDataSet(ByVal callback As System.AsyncCallback, _
          ByVal stateObject As Object, ByVal behavior As CommandBehavior) As System.IAsyncResult   
             Dim res As IAsyncResult = Nothing
             Me.Open()
             res = cmd.BeginExecuteReader(callback, stateObject, behavior)
             Return res
       End Function

But how is that different to BeginExecuteReader? It is not it is exactly the same, I don't see the need to rewrite the DataAdapter class from scratch to support Asynchronous functions when I can simply use a datareader to populate a dataset. The key differences are in the EndExecuteDataSet Method:

       Public Function EndExecuteDataSet(ByVal asyncResult As System.IAsyncResult) As DataSet   
             Dim ds As Dataset = Nothing
             Dim rdr As SqlClient.SqlDataReader = cmd.EndExecuteReader(asyncResult)
             Dim dt As DataTable = New DataTable()
             dt.Load(rdr)
             ds = New DataSet
             ds.Tables.Add(dt)
             Return ds
       End Function

Calling these methods is therefore no different to calling BeginExecuteReader. For example the following code would work from both an .aspx page or an .ascx control.


    Dim db As Classes.Data.DAL
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'Append async attribute to connection string
        db = New Classes.Data.DAL(String.Concat _
        (ConfigurationManager.ConnectionStrings("MyDB")ConnectionString, ";async=true"))
        db.CommandText = "asyncTest"
        ' Launch data request asynchronously using page async task  
        Page.RegisterAsyncTask(New PageAsyncTask(New BeginEventHandler(AddressOf BeginGetData), _
        New EndEventHandler(AddressOf EndGetData), New EndEventHandler(AddressOf GetDataTimeout), _
        Nothing,True))
    End Sub
    Function BeginGetData(ByVal sender As Object, ByVal e As EventArgs, _
        ByVal cb As AsyncCallback, ByVal state As Object) As IAsyncResult
       Return db.BeginExecuteDataSet(cb, state)  
    End Function
    Sub EndGetData(ByVal ar As IAsyncResult)
        Try
           gv1.DataSource = db.EndExecuteDataSet(ar)
           gv1.DataBind()
        Catch ex As Exception
           lblMsg.Text = ex.ToString()
        Finally
           db.Dispose()
        End Try
    End Sub
    Sub GetDataTimeout(ByVal ar As IAsyncResult)
        db.Dispose()
        lblMsg.Text = "Async connection timed out"
    End Sub

There you have it, a DataSet returned asynchronously, from a Data Access Layer. Download the entire Data Access Layer (zip file contains both Visual Basic and C# versions - 3.05 kb).


Posted by Williarob on Wednesday, December 19, 2007 8:07 AM
Permalink | Comments (0) | Post RSSRSS comment feed