Shared Assemblies and Strongly Named Assemblies (CLR via C#)

The CLR supports two kinds of assemblies: weakly named assemblies and strongly named assemblies.

The real difference between weakly named and strongly named assemblies is that a strongly named assembly is signed with a publisher’s public/private key pair that uniquely identifies the assembly’s publisher.

An assembly can be deployed in two ways: privately or globally. A privately deployed assembly is an assembly that is deployed in the application’s base directory or one of its subdirectories. A weakly named assembly can be deployed only privately.

A strongly named assembly consists of four attributes that uniquely identify the assembly: a file name (without an extension), a version number, a culture identity, and a public key. Since public keys are very large numbers, we frequently use a small hash value derived from a public key. This hash value is called a public key token.

The following figure shows how PE is signed

Because public keys are such large numbers, and a single assembly might reference many assemblies, a large percentage of the resulting file’s total size would be occupied with public key information. To conserve storage space, Microsoft hashes the public key and takes the last8 bytes of the hashed value. These reduced public key values—known as public key tokens—are what are actually stored in an AssemblyRef table. In general, developers and end users will see public key token values much more frequently than full public key values. Note, however, that the CLR never uses public key tokens when making security or trust decisions because it is possible that several public keys could hash to a single public key token.

The Global Assembly Cash (GAC):

If an assembly is to be accessed by multiple applications, the assembly must be placed into a well-known directory, and the CLR must know to look in this directory automatically when a reference to the assembly is detected. This well-known location is called the global assembly cache (GAC), which can usually be found in the following directory (assuming that Windows is installed in the C:\Windows directory):

C:\Windows\Assembly

The GAC directory is structured: It contains many subdirectories, and an algorithm is used to generate the names of these subdirectories. You should never manually copy assembly files into the GAC; instead, you should use tools to accomplish this task. These tools know the GAC’s internal structure and how to generate the proper subdirectory names.

The most common tool for installing strongly named assemblies into the GAC is GACUtil.exe

What is the purpose of “registering” an assembly in the GAC? Well, say two companies each produce an OurLibrary assembly consisting of one file: OurLibrary.dll. Obviously, both of these files can’t go in the same directory because the last one installed would overwrite the first one, surely breaking some application. When you install an assembly into the GAC, dedicated subdirectories are created under the C:\Windows\Assembly directory, and the assembly files are copied into one of these subdirectories.

Consider using delayed signing if you want to install your assemblies to the CAG in development environment.

Figure below illustrates how CLR resolves a referenced type

The above figure is not correct case if the references type is in the .NET Framework assemblies. In this case, CLR loads the file that matches CLR version.

Type Forwarding:

The CLR supports the ability to move a type (class, structure, enum, interface, or delegate) from one assembly to another. For example, in .NET 3.5, the System.TimeZoneInfo class is defined in the System.Core.dll assembly. But in .NET 4.0, Microsoft moved this class to the MSCorLib.dll assembly. Normally, moving a type from one assembly to another would break applications. However, the CLR offers a System.Runtime.CompilerServices.TypeForwardedToAttribute attribute, which can be applied to the original assembly (such asSystem.Core.dll). The parameter that you pass to this attribute’s constructor is of type System.Type and it indicates the new type (that is now defined in MSCorLib.dll) that applications should now use. The CLR’s binder uses this information. Since the TypeForwardedToAttribute’s constructor takes a Type, the assembly containing this attribute will be dependent on the new assembly defining the type. If you take advantage of this feature, then you should also apply the System.Runtime.CompilerServices.TypeForwardedFromAttribute attribute to the type in the new assembly and pass to this attribute’s constructor a string with the full name of the assembly that used to define the type. This attribute typically is used for tools, utilities, and serialization. Since the TypeForwardedFromAttribute’s constructor takes a String, the assembly containing this attribute is not dependent on the assembly that used to define the type.

Publisher Control Policy:

Microsoft offers an XML config file that is used to ease the versioning of any assembly. Simply you (as a publisher for the assembly) can port the new version of your assembly with config file which will tell CLR to load the new assembly (say version 2.0) instead of the previous version (1.0). This is done automatically without any end user interaction.

Further if the end user wants to use the previous version for some reasons and ignores the publishers control policy, he can edit his application configuration file to disable the publisher control policy. Doing this for each application you’ve is not practicl so the solution is to edit the Machine.Config file to apply these changes.

C# Important Definitions and Notes

– Instance variables of the class are accessible only to members of the class this is
known as data hiding

– Predicate methods : methods to test the truth of conditions

– Data abstraction : The client cares about what functionality a class offers, but not about how that functionality is implemented

– The direct base class is the base class from which the derived class explicitly inherits. An indirect base class is any class above the direct base class in the class hierarchy, which defines the inheritance relationships among classes. The class hierarchy begins with class object (which is the C# alias for System.Object in the Framework Class Library), which every class directly or indirectly extends (or "inherits from").

– Notethat base classes tend to be "more general," and derived classes tend to be "more specific."

– Classes can be declared with only two access modifiers public and internal. If there is no access modifier in the class declaration, the class defaults to internal access. This allows the class to be used by all code in the same assembly as the class, but not by code in other assemblies. Within the same assembly as the class, this is equivalent to public access. However, if a class library is referenced from an application, the library’s internal classes will be inaccessible from the code of the application. Similarly, methods, instance variables and other members of a class declared internal are accessible to all code compiled in the same assembly, but not to code in other assemblies.

– Accessing types : private, protected, internal, public

– A base class’s protected internal members can be accessed by members of that base class, by members of its derived classes and by any class in the same assembly.)

– Base class methods must be explicitly declared virtual if they are to be overridden by methods in derived classes

– In fact, the first task of any derived class’s constructor is to call its direct base class’s constructor, either explicitly or implicitly (if no constructor call is specified), to ensure that the instance variables inherited from the base class are initialized properly.

– Class object is the only class that does not have a base class.

– "copy-and-paste" approach is often error prone and time consuming

– The virtual and abstract keywords indicate that a base class method can be overridden in derived classes

– The override modifier declares that a derived class method overrides a virtual or abstract base class method. This modifier also implicitly declares the derived class method virtual and allows it to be overridden in derived classes further down the inheritance hierarchy.

– Inheriting protected instance variables slightly increases performance, because we can directly access the variables in the derived class without incurring the overhead of invoking the set or get accesses of the corresponding property. In most cases, however, it is better to use private instance variables to encourage proper software engineering, and leave code optimization issues to the compiler. Your code will be easier to maintain, modify and debug.

– Using protected instance variables creates several potential problems. First, the derived class object can set an inherited variable’s value directly without using the property’s set accessor. Therefore, a derived class object can assign an invalid value to the variable, thus leaving the object in an inconsistent state

– Declaring base class instance variables private (as opposed to protected) enables
the base class implementation of these instance variables to change without
affecting derived class implementations.

– Localizing the effects of changes like this is a good software engineering practice.

– By using inheritance and by using properties that hide the data and ensure consistency, we have efficiently and effectively constructed a well-engineered class.

– Instantiating a derived class object begins a chain of constructor calls in which the derived class constructor, before performing its own tasks, invokes its direct base class’s constructor either explicitly (via a constructor initializer with the base reference) or implicitly (calling the base class’s default constructor or parameterless constructor). Similarly, if the base class is derived from another class (as every class except object is), the base class constructor invokes the constructor of the next class up in the hierarchy, and so on. The last constructor called in the chain is always the constructor for class object. The original derived class constructor’s body finishes executing last. Each base class’s constructor manipulates the base class instance variables that the derived class object inherits

– When an application creates a derived class object, the derived class constructor immediately calls the base class constructor (explicitly, via base, or implicitly). The base class constructor’s body executes to initialize the base class’s instance variables that are part of the derived class object, then the derived class constructor’s body executes to initialize the derived class-only instance variables. Even if a constructor does not assign a value to an instance variable, the variable is still initialized to its default value (i.e., 0 for simple numeric types, false for bools and null for references).

– People experienced with such projects say that effective software reuse improves the software development process. Object-oriented programming facilitates software reuse, potentially shortening development time. The availability of substantial and useful class libraries delivers the maximum benefits of software reuse through inheritance. The FCL class libraries that are used by C# tend to be rather general purpose. Many special-purpose class libraries exist and more are being created.

– At the design stage in an object-oriented system, the designer often finds that certain classes are closely related. The designer should "factor out" common members and place them in a base class. Then the designer should use inheritance to develop derived classes, specializing them with capabilities beyond those inherited from the base class.

– Just as designers of non-object-oriented systems should avoid method proliferation, designers of object-oriented systems should avoid class proliferation. Such proliferation creates management problems and can hinder software reusability, because in a huge class library it becomes difficult for a client to locate the most appropriate classes. The alternative is to create fewer classes that provide more substantial functionality, but such classes might prove cumbersome.

– Reading derived class declarations can be confusing, because inherited members are not declared explicitly in the derived classes, but are nevertheless present in them. A similar problem exists in documenting derived class members.

– A class that overrides the method Equals should also override the method GetHashCode to ensure that equal objects have identical hashcodes. The default Equals implementation determines only whether two references refer to the same object in memory

– Finalize : This method cannot be explicitly declared or called. When a class contains a destructor, the compiler implicitly renames it to override the protected method Finalize, which is called only by the garbage collector before it reclaims an object’s memory. The garbage collector is not guaranteed to reclaim an object, thus it is not guaranteed that an object’s Finalize method will execute. When a derived class’s Finalize method executes, it performs its task, then invokes the base class’s Finalize method. Finalize’s default implementation is a placeholder that simply invokes the base class’s Finalize method.

– GetType : Every object knows its own type at execution time. Method GetType returns an object of class Type (namespace System) that contains information about the object’s type, such as its class name (obtained from Type property FullName).

– MemberwiseClone : This protected method, which takes no arguments and returns an object reference, makes a copy of the object on which it is called. The implementation of this method performs a shallow copy instance variable values in one object are copied into another object of the same type. For reference types, only the references are copied.

– ReferenceEquals : This static method takes two object arguments and returns True if two objects are the same instance or if they are null references. Otherwise, it returns false.

– ToString : The default implementation of this method returns the namespace followed by a dot and the class name of the object’s class.

– To override a base class method, a derived class must declare a method with keyword override and with the same signature (method name, number of parameters and parameter types) and return type as the base class method

– Software is said to be fragile or brittle when a small change in the base class can "break" derived class implementation. You should be able to change the base class implementation while still providing the same services to the derived classes.

– Place the keyword base and the dot (.) operator before the base class method name to invoke an overridden base class method from a derived class.

– All classes in C# inherit directly or indirectly from the object class, so its seven methods are inherited by all other classes. These methods are Equals, Finalize, GetHashCode, GetType, MemberwiseClone, ReferenceEquals and ToString

– All array types implicitly inherit from class Array in the System namespace, which in turn extends class object. As a result, like all other objects, an array inherits the members of class object

– We distinguish between the is-a relationship and the has-a relationship. Is-a represents inheritance. In an is-a relationship, an object of a derived class can also be treated as an object of its base class. For example, a car is a vehicle, and a truck is a vehicle. By contrast, has-a represents composition. In a has-a relationship, an object contains as members references to other objects. For example, a car has a steering wheel, and a car object has a reference to a steering wheel object

– In the case of single inheritance, a class is derived from one direct base class

– Abstract Classes

– Concrete Classes

– Dynamic binding or late binding

– Interfaces:

The interface specifies what operations a radio must permit users to perform but does not specify how the operations are performed

An interface is typically used when disparate (i.e., unrelated) classes need to share common methods

  • Exception:

    • is an indication of a problem that occurs during a program’s execution
  • Stack Trace
  • Data maintained in files often is called persistent data
  • Search engines are used to find Web sites. They usually catalog sites by following links from page to page (known as spidering or crawling) and saving identification and classification information for each page. One way that search engines catalog pages is by reading the content in each page’s meta elements, which specify information about a document
  • http://www.deitel.com/books/downloads.html , The http:// indicates that the resource is to be obtained using the HTTP protocol. The middle portion, www.deitel.com, is the server’s fully qualified hostname the name of the computer on which the resource resides. This computer usually is referred to as the host, because it houses and maintains resources. The hostname www.deitel.com is translated into an IP address (68.236.123.125), which identifies the server in a manner similar to how a telephone number uniquely defines a particular phone line. The hostname is translated into an IP address by a domain name system (DNS) server a computer that maintains a database of hostnames and their corresponding IP addresses. This translation operation is called a DNS lookup
  • Client interacting with Web server:

    • The GET request is sent from the client to the Web Server

      • GET /books/downloads.html HTTP/1.1
      • The word GET is an HTTP method indicating that the client wishes to obtain a resource from the server. The remainder of the request provides the path name of the resource (an XHTML document) and the protocol’s name and version number (HTTP/1.1).
    • After it receives the request, the Web Server searches through its system for the resource.

      • Error: HTTP/1.1 404 Not found
    • The server responds to the request with an appropriate message and the resource’s contents

      • The server then sends one or more HTTP headers, which provide additional information about the data that will be sent. In this case, the server is sending an XHTML text document, so the HTTP header for this example reads:

        • Content-type: text/html
          

MIME is an Internet standard:

that specifies data formats so that programs can interpret data correctly. For example, the MIME type text/plain indicates that the sent information is text that can be displayed directly, without any interpretation of the content as XHTML markup. Similarly, the MIME type image/jpeg indicates that the content is a JPEG image. When the browser receives this MIME type, it attempts to display the image

  • The header or set of headers is followed by a blank line, which indicates to the client that the server is finished sending HTTP headers
  • based applications are multitier applications (sometimes referred to as n-tier applications). Multitier applications divide functionality into separate tiers (i.e., logical groupings of functionality). Although tiers can be located on the same computer, the tiers of Web-based applications typically reside on separate computers
  • relative positioning
  • absolute positioning
  • When the XHTML for our page is created, the validator is converted into ECMAScript that performs the validation. ECMAScript is a scripting language that enhances the functionality and appearance of Web pages. ECMAScript is typically executed on the client. Some clients do not support scripting or disable scripting. However, for security reasons, validation is always performed on the server whether or not the script executes on the client

Cookies provide Web developers with a tool for personalizing Web pages. A cookie is a piece of data stored in a small text file on the user’s computer. A cookie maintains information about the client during and between browser sessions. The first time a user visits the Web site, the user’s computer might receive a cookie; this cookie is then reactivated each time the user revisits that site. The collected information is intended to be an anonymous record containing data that is used to personalize the user’s future visits to the site

Web Services

  • In this article you will learn:

    • What a Web service is.
    • How to create Web services.
    • The important part that XML and the XML-based Simple Object Access Protocol play in enabling Web services.
    • The elements that comprise Web services, such as service descriptions and discovery files.
    • How to create a client that uses a Web service.
    • How to use Web services with Windows applications and Web applications.
    • How to use session tracking in Web services to maintain state information for the client.
    • How to pass user-defined types to a Web service.
  • What a Web service is.

    • Web service is a class that allows its methods to be called by methods on other machines via common data formats and protocols, such as XML and HTTP
    • In .NET, the over-the-network method calls are commonly implemented through the Simple Object Access Protocol (SOAP), an XML-based protocol describing how to mark up requests and responses so that they can be transferred via protocols such as HTTP
  • .NET Web Services Basics:

    • A Web service is a software component stored on one machine that can be accessed by an application (or other software component) on another machine over a network. The machine on which the Web service resides is referred to as a remote machine. The application (i.e., the client) that accesses the Web service sends a method call over a network to the remote machine, which processes the call and returns a response over the network to the application
    • Web services and SOAP are platform and language independent, so companies can collaborate via Web services without worrying about the compatibility of their hardware, software and communications technologies
    • To create a Web service in Visual Web Developer, you first create a project of type ASP.NET Web Service. Visual Web Developer then generates the following:

      • files to contain the Web service code (which implements the Web service)
      • an ASMX file (which provides access to the Web service)
      • a DISCO file (which potential clients use to discover the Web service): Discovery of Web services
    • Declaring a method with attribute WebMethod makes the method accessible to other classes through RPCs and is known as exposing a Web method
    • Four types of DISCO files facilitate the discovery process: .disco files, .vsdisco files, .discomap files and .map files
    • DISCO files consist of XML markup that describes for clients the location of Web services. A .disco file is accessed via a Web service’s ASMX page and contains markup specifying references to the documents that define various Web services. The resulting data that is returned from accessing a .disco file is placed in the .discomap file.
    • When a potential client requests a .vsdisco file, XML markup describing the locations of Web services is generated dynamically, then returned to the client. First, the .NET Framework searches for Web services in the directory in which the .vsdisco file is located, as well as that directory’s subdirectories. The .NET Framework then generates XML (using the same syntax as that of a .disco file) that contains references to all the Web services found in this search. Note that a .vsdisco file does not store the markup generated in response to a request. Instead, the .vsdisco file on disk contains configuration settings that specify the .vsdisco file’s behavior. developers can specify in the .vsdisco file certain directories that should not be searched when a client requests a .vsdisco file
    • Web services created using ASP.NET contain the functionality to generate a .disco file when it is requested. This .disco file contains references only to files in the current Web service. Thus, a developer typically places a .vsdisco file at the root of a server; when accessed, this file locates the .disco files for Web services anywhere on the system and uses the markup found in these .disco files to return information about the entire system
    • After locating a Web service, the client must determine the Web service’s functionality and how to use it. For this purpose, Web services normally contain a service description. This is an XML document that conforms to the Web Service Description Language (WSDL) an XML vocabulary that defines the methods a Web service makes available and how clients interact with them. The WSDL document also specifies lower-level information that clients might need, such as the required formats for requests and responses
    • WSDL documents are not meant to be read by developers; rather, WSDL documents are meant to be read by applications, so they know how to interact with the Web services described in the documents
    • When viewed in a Web browser, an ASMX file presents Web method descriptions and links to test pages that allow users to execute sample calls to these methods
    • ASP.NET generates WSDL information dynamically rather than creating an actual WSDL file
    • The protocol that transmits request-and-response messages is also known as the Web service’s wire format or wire protocol, because it defines how information is sent "along the wire." SOAP is the more commonly used wire format, because SOAP messages can be sent using several transport protocols, whereas HTTP POST must use HTTP
    • Using the ASMX page of a Web service to test and debug methods can help you make the Web service more reliable and robust
    • You can enable a client application to consume a Web service by adding a Web reference to the client. This process adds files to the client application that allow the client to access the Web service
    • The WSDL information is used to create a proxy class, which handles all the "plumbing" required for Web method calls i.e., the networking details and the formation of SOAP messages)
    • Whenever the client application calls a Web method, the application actually calls a corresponding method in the proxy class. This method has the same name and parameters as the Web method that is being called, but formats the call to be sent as a request in a SOAP message. The Web service receives this request as a SOAP message, executes the method call and sends back the result as another SOAP message. When the client application receives the SOAP message containing the response, the proxy class deserializes it and returns the results as the return value of the Web method that was called
  • Simple Object Access Protocol (SOAP):

    • The Simple Object Access Protocol (SOAP) is a platform-independent protocol that uses XML to make remote procedure calls, typically over HTTP. Each request and response is packaged in a SOAP message an XML message containing the information that a Web service requires to process the message. SOAP messages are written in XML so that they are human readable and platform independent. Most firewalls security barriers that restrict communication among networks do not restrict HTTP traffic. Thus, XML and HTTP enable computers on different platforms to send and receive SOAP messages with few limitations
    • When a program invokes a Web method, the request and all relevant information are packaged in a SOAP message and sent to the server on which the Web service resides. When the Web service receives this SOAP message, it begins to process the contents (contained in a SOAP envelope), which specify the method that the client wishes to execute and any arguments the client is passing to that method. This process of interpreting a SOAP message’s contents is known as parsing a SOAP message. After the Web service receives and parses a request, the proper method is called with the specified arguments (if there are any), and the response is sent back to the client in another SOAP message. The client parses the response to retrieve the result of the method call
  • Publishing and Consuming Web Services:

    • class WebService, provides members that are useful in determining information about the client and the Web service itself
    • methods that are tagged with the WebMethod attribute exposes a method so that it can be called remotely
    • Specify a namespace for each Web service so that it can be uniquely identified by clients. In general, you should use your company’s domain name as the Web service’s namespace, since company domain names are guaranteed to be unique
    • No method with the WebMethod attribute can be declared static for a client to access a Web method, an instance of that Web service must exist
    • To access the Web service from another computer in your company’s or school’s local area network, you can replace host with the actual name of the computer on which IIS is running
    • Web servers typically receive requests on port 80
    • Adding web services to the consumer computer and make an object from it then using it
  • Web Services Session Tracking:

    • Setting property EnableSession to TRue indicates that session information should be maintained and should be accessible to this method. This is required only for methods that must access the session information. Doing so allows the Web service to use an HttpSessionState object (named Session by ASP.NET) to maintain the deck of cards for each client application that uses this Web service
  • Using Web Services with Web Applications
  • Using user-defined types

    • The Web methods we have demonstrated so far all received and returned simple type values. It is also possible to process user-defined typesknown as custom typesin a Web service. These types can be passed to or returned from Web methods. Web service clients also can use these user-defined types, because the proxy class created for the client contains the type definitions
    • We mentioned earlier that all types passed to and from Web services must be supported by SOAP. How, then, can SOAP support a type that is not even created yet? Custom types that are sent to or from a Web service are serialized, enabling them to be passed in XML format. This process is referred to as XML serialization
    • Classes that are used to specify return types and parameter types for Web methods must meet several requirements:

      • They must provide a public default or parameterless constructor. When a Web service or Web service consumer receives an XML serialized object, the .NET Framework must be able to call this constructor as part of the process of deserializing the object (i.e., converting it back to a C# object)
      • Properties and instance variables that should be serialized in XML format must be declared public. (Note that the public properties can be used to provide access to private instance variables.)
      • Properties that should be serialized must provide both get and set accessors (even if they have empty bodies). Read-only properties are not serialized
  • Wrap Up:

This chapter introduced ASP.NET Web services a technology that enables users to request and receive data via the Internet and promotes software reusability in distributed systems. You learned that a Web service is a class that allows client machines to call the Web service’s methods remotely via common data formats and protocols, such as XML, HTTP and SOAP. We discussed several benefits of this kind of distributed computinge.g., clients can access certain data on remote machines, and clients lacking the processing power necessary to perform specific computations can leverage remote machines’ resources

Strings, Characters and Regular Expressions

  • In this chapter you will learn:

    • To create and manipulate immutable character string objects of class string.
    • To create and manipulate mutable character string objects of class StringBuilder.
    • To manipulate character objects of struct Char.
    • To use regular expressions in conjunction with classes Regex and Match
  • Characters are the fundamental building blocks of C# source code. Every program is composed of characters that, when grouped together meaningfully, create a sequence that the compiler interprets as instructions describing how to accomplish a task. In addition to normal characters, a program also can contain character constants. A character constant is a character that is represented as an integer value, called a character code. For example, the integer value 122 corresponds to the character constant ‘z’. The integer value 10 corresponds to the newline character ‘\n’. Character constants are established according to the Unicode character set, an international character set that contains many more symbols and letters than does the ASCII (American Standard Code for Information Interchange) character set
  • On occasion, a string will contain multiple backslash characters (this often occurs in the name of a file). To avoid excessive backslash characters, it is possible to exclude escape sequences and interpret all the characters in a string literally, using the @ character. Backslashes within the double quotation marks following the @ character are not considered escape sequences, but rather regular backslash characters. Often this simplifies programming and makes the code easier to read
  • This approach also has the advantage of allowing strings to span multiple lines by preserving all newlines, spaces and tabs.
  • Class string provides eight constructors for initializing strings in various ways
  • In most cases, it is not necessary to make a copy of an existing string. All strings are immutabletheir character contents cannot be changed after they are created. Also, if there are one or more references to a string (or any object for that matter), the object cannot be reclaimed by the garbage collector
  • Attempting to access a character that is outside a string’s bounds (i.e., an index less than 0 or an index greater than or equal to the string’s length) results in an IndexOutOfRangeException
  • Computers can order characters alphabetically because the characters are represented internally as Unicode numeric codes. When comparing two strings, C# simply compares the numeric codes of the characters in the strings
  • Method Equals uses a lexicographical comparison the integer Unicode values that represent each character in each string is compared. A comparison of the string "hello" with the string "HELLO" would return false, because the numeric representations of lowercase letters are different from the numeric representations of corresponding uppercase letters
  • Method StartsWith determines whether a string instance starts with the string text passed to it as an argument. Method EndsWith determines whether a string instance ends with the string text passed to it as an argument
  • There are three versions of LastIndexOf. 1st version of the method LastIndexOf that takes as an argument the character for which to search. Second version of the method LastIndexOf takes two arguments the character for which to search and the highest index from which to begin searching backward for the character. Third version of the method LastIndexOf takes three arguments the character for which to search, the starting index from which to start searching backward and the number of characters (the portion of the string) to search
  • Class string provides two Substring methods, which are used to create a new string by copying part of an existing string. Each method returns a new string
  • The 1sy version of Substring method that takes one int argument. The argument specifies the starting index from which the method copies characters in the original string. The substring returned contains a copy of the characters from the starting index to the end of the string. If the index specified in the argument is outside the bounds of the string, the program throws an ArgumentOutOfRangeException
  • The second version of method Substring takes two int arguments. The first argument specifies the starting index from which the method copies characters from the original string. The second argument specifies the length of the substring to be copied. The substring returned contains a copy of the specified characters from the original string
  • String concatenation: Concat
  • Class string provides several methods that return modified copies of strings like Replace, ToLower, ToUpper and trim
  • Replace: can differ between capital letters and small letters
  • Method Replace takes two arguments a string for which to search and another string with which to replace all matching occurrences of the first argument. The original string remains unchanged. If there are no occurrences of the first argument in the string, the method returns the original string
  • Method trim removes all whitespace characters that appear at the beginning and end of a string. Without otherwise altering the original string, the method returns a new string that contains the string, but omits leading or trailing whitespace characters. Another version of method trim takes a character array and returns a string that does not contain the characters in the array argument
  • The string class provides many capabilities for processing strings. However a string’s contents can never change. Operations that seem to concatenate strings are in fact assigning string references to newly created strings (e.g., the += operator creates a new string and assigns the initial string reference to the newly created string).
  • The features of class StringBuilder (namespace System.Text), used to create and manipulate dynamic string information i.e., mutable strings. Every StringBuilder can store a certain number of characters that is specified by its capacity. Exceeding the capacity of a StringBuilder causes the capacity to expand to accommodate the additional characters. As we will see, members of class StringBuilder, such as methods Append and AppendFormat, can be used for concatenation like the operators + and += for class string
  • Objects of class string are immutable (i.e., constant strings), whereas object of class StringBuilder are mutable. C# can perform certain optimizations involving strings (such as the sharing of one string among multiple references), because it knows these objects will not change
  • The no-parameter StringBuilder constructor to create a StringBuilder that contains no characters and has a default initial capacity of 16 characters
  • lass StringBuilder provides the Length and Capacity properties to return the number of characters currently in a StringBuilder and the number of characters that a StringBuilder can store without allocating more memory, respectively. These properties also can increase or decrease the length or the capacity of the StringBuilder
  • Method EnsureCapacity allows you to reduce the number of times that a StringBuilder’s capacity must be increased. The method doubles the StringBuilder instance’s current capacity. If this doubled value is greater than the value that the programmer wishes to ensure, that value becomes the new capacity. Otherwise, EnsureCapacity alters the capacity to make it equal to the requested number
  • Assigning null to a string reference can lead to logic errors if you attempt to compare null to an empty string. The keyword null is a value that represents a null reference (i.e., a reference that does not refer to an object), not an empty string (which is a string object that is of length 0 and contains no characters)
  • Class StringBuilder provides 19 overloaded Append methods that allow various types of values to be added to the end of a StringBuilder. The FCL provides versions for each of the simple types and for character arrays, strings and objects. (Remember that method ToString produces a string representation of any object.) Each of the methods takes an argument, converts it to a string and appends it to the StringBuilder
  • Class StringBuilder also provides method AppendFormat, which converts a string to a specified format, then appends it to the StringBuilder
  • The information enclosed in braces specifies how to format a specific piece of data. Formats have the form {X[,Y][:FormatString]}, where X is the number of the argument to be formatted, counting from zero. Y is an optional argument, which can be positive or negative, indicating how many characters should be in the result. If the resulting string is less than the number Y, the string will be padded with spaces to make up for the difference. A positive integer aligns the string to the right; a negative integer aligns it to the left. The optional FormatString applies a particular format to the argument currency, decimal or scientific, among others. In this case, "{0}" means the first argument will be printed out. "{1:C}" specifies that the second argument will be formatted as a currency value
  • The format "{0:d3}", specifies that the first argument will be formatted as a three-digit decimal, meaning any number that has fewer than three digits will have leading zeros placed in front to make up the difference
  • Class StringBuilder provides 18 overloaded Insert methods to allow various types of data to be inserted at any position in a StringBuilder. The class provides versions for each of the simple types and for character arrays, strings and objects. Each method takes its second argument, converts it to a string and inserts the string into the StringBuilder in front of the character in the position specified by the first argument. The index specified by the first argument must be greater than or equal to 0 and less than the length of the StringBuilder; otherwise, the program throws an ArgumentOutOfRangeException
  • Class StringBuilder also provides method Remove for deleting any portion of a StringBuilder. Method Remove takes two argumentsthe index at which to begin deletion and the number of characters to delete. The sum of the starting index and the number of characters to be deleted must always be less than the length of the StringBuilder; otherwise, the program throws an ArgumentOutOfRangeException
  • Another useful method included with StringBuilder is Replace. Replace searches for a specified string or character and substitutes another string or character in its place
  • An overload of Replace that takes four parameters, the first two of which are characters and the second two of which are ints. The method replaces all instances of the first character with the second character, beginning at the index specified by the first int and continuing for a count specified by the second int.
  • C# provides a type called a struct (short for structure) that is similar to a class. Although structs and classes are comparable in many ways, structs represent value types. Like classes, structs can have methods and properties, and can use the access modifiers public and private. Also, struct members are accessed via the member access operator (.)
  • The simple types are actually aliases for struct types. For instance, an int is defined by struct System.Int32, a long by System.Int64 and so on. All struct types derive from class ValueType, which in turn derives from object. Also, all struct types are implicitly sealed, so they do not support virtual or abstract methods, and their members cannot be declared protected or protected internal
  • Regular Expressions and Class Regex:

    • Regular expressions are specially formatted strings used to find patterns in text. They can be useful during information validation, to ensure that data is in a particular format. For example, a ZIP code must consist of five digits, and a last name must start with a capital letter. Compilers use regular expressions to validate the syntax of programs. If the program code does not match the regular expression, the compiler indicates that there is a syntax error
    • The .NET Framework provides several classes to help developers recognize and manipulate regular expressions. Class Regex (of the System.Text.RegularExpressions namespace) represents an immutable regular expression. Regex method Match returns an object of class Match that represents a single regular expression match. Regex also provides method Matches, which finds all matches of a regular expression in an arbitrary string and returns an object of the class MatchCollection object containing all the Matches. A collection is a data structure, similar to an array and can be used with a foreach statement to iterate through the collection’s elements.
  • Regular Expression Character Classes:

    • The following table specifies some character classes that can be used with regular expressions. Please do not confuse a character class with a C# class declaration. A character class is simply an escape sequence that represents a group of characters that might appear in a string

Character Class

Matches

\d

Any digit

\w

Any word character

\s

Any white space

\D

Any non-digit

\W

Any non-word character

\S

Any non-white space

.

Any thing

  • A word character is any alphanumeric character or underscore. A whitespace character is a space, a tab, a carriage return, a newline or a form feed. A digit is any numeric character. Regular expressions are not limited to the character classes previous table. As you will see in our first example "RegexMatches, regular expressions can use other notations to search for complex patterns in strings
  • See Article Project: RegexMatches Project
  • Talking about the project:

    • We precede the string with @. Recall that backslashes within the double quotation marks following the @ character are regular backslash characters, not the beginning of escape sequences. To define the regular expression without prefixing @ to the string, you would need to escape every backslash character, as in
    • "J.*\\d[0-35-9]-\\d\\d-\\d\\d"
    • Which makes the regular expression more difficult to read?
    • The first character in the regular expression, "J", is a literal character. Any string matching this regular expression is required to start with "J". In a regular expression, the dot character "." matches any single character except a newline character. When the dot character is followed by an asterisk, as in ".*", the regular expression matches any number of unspecified characters except newlines. In general, when the operator "*" is applied to a pattern, the pattern will match zero or more occurrences. By contrast, applying the operator "+" to a pattern causes the pattern to match one or more occurrences. For example, both "A*" and "A+" will match "A", but only "A*" will match an empty string
    • "\d" matches any numeric digit. To specify sets of characters other than those that belong to a predefined character class, characters can be listed in square brackets, []. For example, the pattern "[aeiou]" matches any vowel. Ranges of characters are represented by placing a dash (-) between two characters. In the example, "[0-35-9]" matches only digits in the ranges specified by the pattern i.e., any digit between 0 and 3 or between 5 and 9; therefore, it matches any digit except 4. You can also specify that a pattern should match anything other than the characters in the brackets. To do so, place ^ as the first character in the brackets. It is important to note that "[^4]" is not the same as "[0-35-9]"; "[^4]" matches any non-digit and digits other than 4.
    • Although the "" character indicates a range when it is enclosed in square brackets, instances of the "-" character outside grouping expressions are treated as literal characters. Thus, the regular expression in line 12 searches for a string that starts with the letter "J", followed by any number of characters, followed by a two-digit number (of which the second digit cannot be 4), followed by a dash, another two-digit number, a dash and another two-digit number
  • Quantifiers:

    • The asterisk (*) is more formally called a quantifier. The following table lists various quantifiers that you can place after a pattern in a regular expression and the purpose of each quantifier
    • All of the quantifiers are greedy they will match as many occurrences of the pattern as possible until the pattern fails to make a match. If a quantifier is followed by a question mark (?), the quantifier becomes lazy and will match as few occurrences as possible as long as there is a successful match

Quantifier

Matches

*

Matches zero or more occurrences of the preceding pattern

+

Matches one or more occurrences of the preceding pattern

?

Matches zero or one occurrences of the preceding pattern

{n}

Matches exactly n occurrences of the preceding pattern

{n,}

Matches at least n occurrences of the preceding pattern

{n,m}

Matches between n and m (inclusive) occurrences of the preceding pattern

  • The Windows application "Validating user information using regular expressions" presents a more involved example that uses regular expressions to validate name, address and telephone number information input by a user.
  • See Article Projects: Validating user information using regular expressions:

    • In the Zip Code Regular Expression: Note that without the "^" and "$" characters, the regular expression would match any five consecutive digits in the string. By including the "^" and "$" characters, we ensure that only five-digit zip codes are allowed
  • In a regular expression that begins with a "^" character and ends with a "$" character, the characters "^" and "$" represent the beginning and end of a string, respectively. These characters force a regular expression to return a match only if the entire string being processed matches the regular expression

The character "|" matches the expression to its left or the expression to its right. For example, Hi (John|Jane) matches both Hi John and Hi Jane. In line 55, we use the character "|" to indicate that the address can contain a word of one or more characters or a word of one or more characters followed by a space and another word of one or more characters. Note the use of parentheses to group parts of the regular expression. Quantifiers may be applied to patterns enclosed in parentheses to create more complex regular expressions

Operator Overloading

  • Definition:

    • Enabling C# mathematical operators to be suitable for your own created classes
  • Example:

        public static ClassName operator+( object1 x, object2 y )
    

        {

  • // new object that contains the result

       return new ClassName(); 
    } 
  • Notes:

At least one argument of an overloaded operator method must be a reference to an object of the class in which the operator is overloaded. This prevents programmers from changing how operators work on simple types

Networking: Streams-Based Sockets and Datagrams

  • In this article you will learn:

    • To implement networking applications that use sockets and datagrams.
    • To implement clients and servers that communicates with one another.
    • To implement network-based collaborative applications.
    • To construct a multithreaded server.
    • To use the WebBrowser control to add Web browsing capabilities to any application.
    • To use .NET remoting to enable an application executing on one computer to invoke methods from an application executing on a different computer
  • Introduction:

    • This article begins with an overview of the communication techniques and technologies used to transmit data over the Internet. Next, we present the basic concepts of establishing a connection between two applications using streams of data that are similar to File I/O. This connection-oriented approach enables programs to communicate with one another as easily as writing to and reading from files on disk. Then we present a simple chat application that uses these techniques to send messages between a client and a server. The article continues with a presentation and an example of connectionless techniques for transmitting data between applications that is less reliable than establishing a connection between applications, but much more efficient. Such techniques are typically used in applications such as streaming audio and video over the Internet. Next, we present an example of a client-server Tic-Tac-Toe game that demonstrates how to create a simple multithreaded server. Then this article demonstrates the new WebBrowser control for adding Web browsing capabilities to any application
  • Connection-Oriented vs. Connectionless Communication:

    • There are two primary approaches to communicating between applications connection oriented and connectionless. Connection-oriented communications are similar to the telephone system, in which a connection is established and held for the length of the session. Connectionless services are similar to the postal service, in which two letters mailed from the same place and to the same destination may actually take two dramatically different paths through the system and even arrive at different times, or not at all
    • In a connection-oriented approach, computers send each other control information through a technique called handshaking to initiate an end-to-end connection. The Internet is an unreliable network, which means that data sent across the Internet may be damaged or lost. Data is sent in packets, which contain pieces of the data along with information that helps the Internet route the packets to the proper destination. The Internet does not guarantee anything about the packets sent; they could arrive corrupted or out of order, as duplicates or not at all. The Internet makes only a "best effort" to deliver packets. A connection-oriented approach ensures reliable communications on unreliable networks, guaranteeing that sent packets will arrive at the intended receiver undamaged and be reassembled in the correct sequence
    • In a connectionless approach, the two computers do not handshake before transmission, and reliability is not guaranteed, data sent may never reach the intended recipient. A connectionless approach, however, avoids the overhead associated with handshaking and enforcing reliability less information often needs to be passed between the hosts
  • Protocols for Transporting Data:

    • Protocols are sets of rules that govern how two entities should interact
    • .NET’s TCP and UDP networking capabilities are defined in the System.Net.Sockets namespace.
    • Transmission Control Protocol (TCP) is a connection-oriented communication protocol which guarantees that sent packets will arrive at the intended receiver undamaged and in the correct sequence. TCP allows protocols like HTTP to send information across a network as simply and reliably as writing to a file on a local computer. If packets of information don’t arrive at the recipient, TCP ensures that the packets are sent again. If the packets arrive out of order, TCP reassembles them in the correct order transparently to the receiving application. If duplicate packets arrive, TCP discards them
    • Applications that do not require TCP’s reliable end-to-end transmission guaranty typically use the connectionless User Datagram Protocol (UDP). UDP incurs the minimum overhead necessary to communicate between applications. UDP makes no guarantees that packets, called datagrams, will reach their destination or arrive in their original order
    • There are benefits to using UDP over TCP. UDP has little overhead because UDP datagrams do not need to carry the information that TCP packets carry to ensure reliability. UDP also reduces network traffic relative to TCP due to the absence of handshaking, retransmissions, etc
    • Unreliable communication is acceptable in many situations. First, reliability is not necessary for some applications, so the overhead imposed by a protocol that guarantees reliability can be avoided. Second, some applications, such as streaming audio and video, can tolerate occasional datagram loss. This usually results in a small pause (or "hiccup") in the audio or video being played. If the same application were run over TCP, a lost segment could cause a significant pause, since the protocol would wait until the lost segment was retransmitted and delivered correctly before continuing. Finally, applications that need to implement their own reliability mechanisms different from those provided by TCP can build such mechanisms over UDP
  • Establishing a Simple TCP Server (Using Stream Sockets)

    • Establishing a simple server with TCP and stream sockets requires five steps:

      • First, create an object of class TcpListener of namespace System.Net.Sockets

        • This class represents a TCP stream socket through which a server can listen for requests

          • TcpListener server = new TcpListener( ipAddress, port );
            
        • Binds the server application to the specified port number. A port number is a numeric identifier that an application uses to identify itself at a given network address, also known as an Internet Protocol Address (IP Address)
        • Addresses identify computers on the Internet. In fact, Web-site names, such as www.deitel.com, are aliases for IP addresses. An IP address is represented by an object of class IPAddress of namespace System.Net. Any application that performs networking identifies itself via an IP address/port number pair no two applications can have the same port number at a given IP address
        • Port numbers can have values between 0 and 65535. Many operating systems reserve port numbers below 1024 for system services (such as e-mail and Web servers). Applications must be granted special privileges to use these reserved port numbers
      • Second, call TcpListener’s Start method, which causes the TcpListener object to begin listening for connection requests

        • An object of class Socket (namespace System.Net.Sockets) manages a connection to a client. Method AcceptSocket of class TcpListener accepts a connection request
        • Socket connection = server.AcceptSocket();
      • Third, establishing the streams used for communication with the client

        • In this step, we create a NetworkStream object that uses the Socket object representing the connection to perform the actual sending and receiving of data
      • Fourth, processing phase, in which the server and client communicate using the connection established in the third step

        • this phase, the client uses BinaryWriter method Write and BinaryReader method ReadString to perform the appropriate communications
      • Fifth, the connection-termination phase

        • When the client and server have finished communicating, the server calls method Close of the BinaryReader, BinaryWriter, NetworkStream and Socket to terminate the connection. The server can then return to step two to wait for the next connection request. Note that the documentation for class Socket recommends that you call method Shutdown before method Close to ensure that all data is sent and received before the Socket closes
      • One problem associated with the server scheme described in this section is that step four blocks other requests while processing the connected client’s request, so no other client can connect with the server while the code that defines the processing phase is executing. The most common technique for addressing this problem is to use multithreaded servers, which place the processing-phase code in a separate thread. For each connection request the server receives, it creates a Thread to process the connection, leaving its TcpListener (or Socket) free to receive other connections
      • In high-performance systems with abundant memory, a multithreaded server can be implemented to create a pool of threads. These threads can be assigned quickly to handle network I/O across multiple Sockets. Thus, when a connection is received, the server does not incur the overhead of thread creation
  • Multithreading

    • Multithreading can increase performance on single processor systems that simulate concurrency when one thread cannot proceed, another can use the processor
    • We discuss many applications of concurrent programming. When programs download large files, such as audio clips or video clips over the Internet, users do not want to wait until an entire clip downloads before starting the playback. To solve this problem, we can put multiple threads to work one thread downloads a clip, while another plays the clip. These activities proceed concurrently. To avoid choppy playback, we synchronize the threads so that the player thread does not begin until there is a sufficient amount of the clip in memory to keep the player thread busy
    • Another example of multithreading is the CLR’s automatic garbage collection. C and C++ require programmers to reclaim dynamically allocated memory explicitly. The CLR provides a garbage-collector thread, which reclaims dynamically allocated memory that is no longer needed
    • Set an object reference to null when the program no longer needs that object. This enables the garbage collector to determine at the earliest possible moment that the object can be garbage collected. If such an object has other references to it, that object cannot be collected
    • Thread States: Life Cycle of a Thread:

      • A Thread object begins its life cycle in the Unstarted state when the program creates the object and passes a ThreadStart delegate to the object’s constructor. The TtreadStart delegate, which specifies the actions the thread will perform during its life cycle, must be initialized with a method that returns void and takes no arguments. [Note: .NET 2.0 also includes a ParameterizedThreadStart delegate to which you can pass a method that takes arguments. For more information, visit the site msdn2.microsoft.com/en-us/library/xzehzsds.] The thread remains in the Unstarted state until the program calls the Thread’s Start method, which places the thread in the Running state and immediately returns control to the part of the program that called Start. Then the newly Running thread and any other threads in the program can execute concurrently on a multiprocessor system or share the processor on a system with a single processor
      • While in the Running state, the thread may not actually be executing all the time. The thread executes in the Running state only when the operating system assigns a processor to the thread. When a Running thread receives a processor for the first time, the thread begins executing the method specified by its ThreadStart delegate
      • A Running thread enters the Stopped (or Aborted) state when its ThreadStart delegate terminates, which normally indicates that the thread has completed its task. Note that a program can force a thread into the Stopped state by calling Thread method Abort on the appropriate Thread object. Method Abort throws a ThreadAbortException in the thread, normally causing the thread to terminate. When a thread is in the Stopped state and there are no references to the thread object, the garbage collector can remove the thread object from memory. [Note: Internally, when a thread’s Abort method is called, the thread actually enters the AbortRequested state before entering the Stopped state. The thread remains in the AbortRequested state while waiting to receive the pending ThreadAbortException. When Abort is called, if the thread is in the WaitSleepJoin, Suspended or Blocked state, the thread resides in its current state and the AbortRequested state, and cannot receive the ThreadAbortException until it leaves its current state.]
      • A thread is considered Blocked if it is unable to use a processor even if one is available. For example, a thread becomes blocked when it issues an input/output (I/O) request. The operating system blocks the thread from executing until the operating system can complete the I/O request for which the thread is waiting. At that point, the thread returns to the Running state, so it can resume execution. Another case in which a thread becomes blocked is in thread synchronization. A thread being synchronized must acquire a lock on an object by calling Monitor method Enter. If a lock is not available, the thread is blocked until the desired lock becomes available. [Note: The Blocked state is not an actual state in .NET. It is a conceptual state that describes a thread that is not Running.]
      • There are three ways in which a Running thread enters the WaitSleepJoin state. If a thread encounters code that it cannot execute yet (normally because a condition is not satisfied), the thread can call Monitor method Wait to enter the WaitSleepJoin state. Once in this state, a thread returns to the Running state when another thread invokes Monitor method Pulse or PulseAll. Method Pulse moves the next waiting thread back to the Running state. Method PulseAll moves all waiting threads back to the Running state
      • A Running thread can call Thread method Sleep to enter the WaitSleepJoin state for a period of milliseconds specified as the argument to Sleep. A sleeping thread returns to the Running state when its designated sleep time expires. Sleeping threads cannot use a processor, even if one is available
      • Any thread that enters the WaitSleepJoin state by calling Monitor method Wait or by calling Thread method Sleep also leaves the WaitSleepJoin state and returns to the Running state if the sleeping or waiting Thread’s Interrupt method is called by another thread in the program. The Interrupt method causes a ThreadInterruptionException to be thrown in the interrupted thread
      • If a thread cannot continue executing (we will call this the dependent thread) unless another thread terminates, the dependent thread calls the other thread’s Join method to "join" the two threads. When two threads are "joined," the dependent thread leaves the WaitSleepJoin state and re-enters the Running state when the other thread finishes execution (enters the Stopped state).
      • If a Running Thread’s Suspend method is called, the Running thread enters the Suspended state. A Suspended thread returns to the Running state when another thread in the program invokes the Suspended thread’s Resume method. [Note: Internally, when a thread’s Suspend method is called, the thread actually enters the SuspendRequested state before entering the Suspended state. The thread remains in the SuspendRequested state while waiting to respond to the Suspend request. If the thread is in the WaitSleepJoin state or is blocked when its Suspend method is called, the thread resides in its current state and the SuspendRequested state, and cannot respond to the Suspend request until it leaves its current state.] Methods Suspend and Resume are now deprecated and should not be used
      • If a thread’s IsBackground property is set to true, the thread resides in the Background state. A thread can reside in the Background state and any other state simultaneously. A process must wait for all foreground threads (threads not in the Background state) to finish executing and enter the Stopped state before the process can terminate. However, if the only threads remaining in a process are Background threads, the CLR terminates each thread by invoking its Abort method, and the process terminates
    • Every thread has a priority in the range between ThreadPriority.Lowest to ThreadPriority.Highest. These values come from the Thread Priority enumeration (namespace System.Threading), which consists of the values Lowest, Below Normal, Normal, AboveNormal and Highest. By default, each thread has priority Normal.
    • The Windows operating system supports a concept, called time slicing, that enables threads of equal priority to share a processor. Without time slicing, each thread in a set of equal-priority threads runs to completion (unless the thread leaves the Running state and enters the WaitSleepJoin, Suspended or Blocked state) before the thread’s peers get a chance to execute. With time slicing, each thread receives a brief burst of processor time, called a quantum, during which the thread can execute. At the completion of the quantum, even if the thread has not finished executing, the processor is taken away from that thread and given to the next thread of equal priority, if one is available
    • The job of the thread scheduler is to keep the highest-priority thread running at all times and, if there is more than one highest-priority thread, to ensure that all such threads execute for a quantum in round-robin fashion
    • thread’s priority can be adjusted with the Priority property, which accepts values from the ThreadPriority enumeration. If the value specified is not one of the valid thread-priority constants, an ArgumentException occurs.
    • A thread executes until it dies, becomes Blocked for I/O (or some other reason), calls Sleep, calls Monitor method Wait or Join, is pre-empted by a thread of higher priority or has its quantum expire. A thread with a higher priority than the Running thread can become Running (and hence pre-empt the first Running thread) if a sleeping thread wakes up, if I/O completes for a thread that Blocked for that I/O, if either Pulse or PulseAll is called on an object on which Wait was called, if a thread is Resumed from the Suspended state or if a thread to which the high-priority thread was joined completes
    • See the Article Solution: Project "Multithreading (Get Started)"
    • Thread Synchronization and Class Monitor:

      • Often, multiple threads of execution manipulate shared data. If threads with access to shared data simply read that data, then any number of threads could access that data simultaneously and no problems would arise. However, when multiple threads share data and that data is modified by one or more of those threads, and then indeterminate results may occur. If one thread is in the process of updating the data and another thread tries to update it too, the data will reflect only the later update. If the data is an array or other data structure in which the threads could update separate parts of the data concurrently, it is possible that part of the data will reflect the information from one thread while part of the data will reflect information from another thread. When this happens, the program has difficulty determining when the data has been updated properly
      • The problem can be solved by giving one thread at a time exclusive access to code that manipulates the shared data. During that time, other thread wishing to manipulate the data should be kept waiting. When the thread with exclusive access to the data completes its data manipulations, one of the waiting threads should be allowed to proceed. In this fashion, each thread accessing the shared data excludes all other threads from doing so simultaneously. This is called mutual exclusion or thread synchronization
      • C# uses the .NET Framework’s monitors to perform synchronization. Class Monitor provides the methods for locking objects to implement synchronized access to shared data. Locking an object means that only one thread can access that object at a time. When a thread wishes to acquire exclusive control over an object, the thread invokes Monitor method Enter to acquire the lock on that data object. Each object has a SyncBlock that maintains the state of that object’s lock. Methods of class Monitor use the data in an object’s SyncBlock to determine the state of the lock for that object. After acquiring the lock for an object, a thread can manipulate that object’s data. While the object is locked, all other threads attempting to acquire the lock on that object are blocked from acquiring the locksuch threads enter the Blocked state. When the thread that locked the shared object no longer requires the lock, that thread invokes Monitor method Exit to release the lock. This updates the SyncBlock of the shared object to indicate that the lock for the object is available again. At this point, if there is a thread that was previously blocked from acquiring the lock on the shared object, that thread acquires the lock to begin its processing of the object. If all threads with access to an object attempt to acquire the object’s lock before manipulating the object, only one thread at a time will be allowed to manipulate the object. This helps ensure the integrity of the data
      • Deadlock occurs when a waiting thread (let us call this thread1) cannot proceed because it is waiting (either directly or indirectly) for another thread (let us call this thread2) to proceed, while simultaneously thread2 cannot proceed because it is waiting (either directly or indirectly) for thread1 to proceed. Two threads are waiting for each other, so the actions that would enable either thread to continue execution never occur
      • lock ( objectReference )

           {

      // code that requires synchronization goes here

           }

      • if a thread that owns the lock on an object determines that it cannot continue with its task until some condition is satisfied, the thread should call Monitor method Wait and pass as an argument the object on which the thread will wait until the thread can perform its task. Calling method Monitor.Wait from a thread releases the lock the thread has on the object that Wait receives as an argument and places that thread in the WaitSleepJoin state for that object. A thread in the WaitSleepJoin state of a specific object leaves that state when a separate thread invokes Monitor method Pulse or PulseAll with that object as an argument. Method Pulse transitions the object’s first waiting thread from the WaitSleepJoin state to the Running state. Method PulseAll transitions all threads in the object’s WaitSleepJoin state to the Running state. The transition to the Running state enables the thread (or threads) to get ready to continue executing
      • There is a difference between threads waiting to acquire an object’s lock and threads waiting in an object’s WaitSleepJoin state. Threads that call Monitor method Wait with an object as an argument are placed in that object’s WaitSleepJoin state. Threads that are simply waiting to acquire the lock enter the conceptual Blocked state and wait until the object’s lock becomes available. Then, a Blocked thread can acquire the object’s lock
      • Monitor methods Enter, Exit, Wait, Pulse and PulseAll all take a reference to an object usually keyword this as their argument
      • A thread in the WaitSleepJoin state cannot re-enter the Running state to continue execution until a separate thread invokes Monitor method Pulse or PulseAll with the appropriate object as an argument. If this does not occur, the waiting thread will wait forever essentially the equivalent of deadlock
      • When multiple threads manipulate a shared object using monitors, ensure that if one thread calls Monitor method Wait to enter the WaitSleepJoin state for the shared object, a separate thread eventually will call Monitor method Pulse to transition the thread waiting on the shared object back to the Running state. If multiple threads may be waiting for the shared object, a separate thread can call Monitor method PulseAll as a safeguard to ensure that all waiting threads have another opportunity to perform their tasks. If this is not done, indefinite postponement or deadlock could occur
      • Synchronization to achieve correctness in multithreaded programs can make programs run more slowly, as a result of monitor overhead and the frequent transitioning of threads between the WaitSleepJoin and Running states. There is not much to say, however, for highly efficient, yet incorrect multithreaded programs!
    • Producer/Consumer Relationship without Thread Synchronization:

      • In a producer/consumer relationship, the producer portion of an application generates data and the consumer portion of an application uses that data. In a multithreaded producer/consumer relationship, a producer thread calls a produce method to generate data and place it in a shared region of memory, called a buffer. A consumer thread calls a consume method to read that data. If the producer wishes to put the next data in the buffer but determines that the consumer has not yet read the previous data from the buffer, the producer thread should call Wait. Otherwise, the consumer would never see the previous data, which would be lost to that application. When the consumer thread reads the data, it should call Pulse to allow a waiting producer to proceed, since there is now free space in the buffer. If a consumer thread finds the buffer empty or finds that the previous data has already been read, the consumer should call Wait. Otherwise, the consumer might read "garbage" from the buffer, or the consumer might process a previous data item more than once each of these possibilities results in a logic error in the application. When the producer places the next data into the buffer, the producer should call Pulse to allow the consumer thread to proceed and read that data
      • See the Article Solution: Project "ProducerConsumerWithoutSync"
      • To solve the problems of lost data and data consumed more than once in the previous project, we will synchronize the access of the concurrent producer and consumer threads to the code that manipulates the shared data by using Monitor class methods Enter, Wait, Pulse and Exit. When a thread uses synchronization to access a shared object, the object is locked, so no other thread can acquire the lock for that shared object at the same time
    • Producer/Consumer Relationship with Thread Synchronization:

      • Forgetting to release the lock on an object when that lock is no longer needed is a logic error. This will prevent the threads in your program from acquiring the lock to proceed with their tasks. These threads will be forced to wait (unnecessarily, because the lock is no longer needed). Such waiting can lead to deadlock and indefinite postponement
      • See the Article Solution: Project "ProducerConsumerWithSync"
    • Producer/Consumer Relationship: Circular Buffer:

      • To minimize the waiting for threads that share resources and operate at the same relative speeds, we can implement a circular buffer that provides extra locations in which the producer can place values (if it "gets ahead" of the consumer) and from which the consumer can retrieve those values (if it "catches up" to the producer). Let us assume the buffer is implemented as an array. The producer and consumer work from the beginning of the array. When either thread reaches the end of the array, it simply returns to the first element of the array to perform its next task. If the producer temporarily produces values faster than the consumer can consume them, the producer can write additional values in the extra buffers (if cells are available; otherwise, the producer must, once again, wait). This enables the producer to perform its task even though the consumer is not ready to receive the current value being produced. Similarly, if the consumer consumes faster than the producer produces new values, the consumer can read additional values from the buffer (if there are any; otherwise, the consumer must, once again, wait) and thus "catch up" to the producer. This enables the consumer to perform its task even though the producer is not ready to produce additional values.
      • Note that a circular buffer would be inappropriate if the producer and consumer operate at different speeds. If the consumer always executes faster than the producer, then a buffer with one location is enough. Additional locations would waste memory. If the producer always executes faster, a buffer with an infinite number of locations would be required to absorb the extra production.
      • The key to using a circular buffer is to define it with enough extra cells to handle the anticipated "extra" production. If, over a period of time, we determine that the producer often produces as many as three more values than the consumer can consume, we can define a buffer of at least three cells to handle the extra production. We do not want the buffer to be too small, because that would cause threads to wait more. On the other hand, we do not want the buffer to be too large, because that would waste memory
      • The key to using a circular buffer is optimizing the buffer size to minimize the amount of thread wait time
    • Using a lock block to manage the lock on a synchronized object eliminates the possibility of forgetting to relinquish the lock with a call to Monitor method Exit. C# implicitly calls Monitor method Exit when a lock block terminates for any reason. Thus, even if an exception occurs in the block, the lock will be released
    • Multithreading with GUIs:

      • The nature of multithreaded programming prevents you from knowing exactly when a thread will execute. Windows form components are not thread safeif multiple threads manipulate a Windows GUI component, the results may not be correct. To ensure that threads manipulate GUI components in a thread-safe manner, all interactions with GUI components should be performed by the User Interface thread (also known as the UI thread)the thread that creates and maintains the GUI. Class Control provides method Invoke to help with this process. Method Invoke specifies GUI processing statements that the UI thread should execute. The method receives as its arguments a delegate representing a method that will modify the GUI and an optional array of objects representing the parameters to the method. At some point after Invoke is called, the UI thread will execute the method represented by the delegate, passing the contents of the object array as the method’s arguments
      • In the GUI threading project, The Exit method of class System.Environment with the ExitCode property as argument. This causes all other threads in this application to terminate. Otherwise, only the UI thread would be terminated when the user closes this application; Thread1, Thread2 and Thread3 would continue executing forever
      • See the Article Solution: Project "MultithreadingWithGUIs"
    • Wrap up:

      • In this chapter, you learned basic capabilities of the .NET framework that enable you to specify concurrent tasks in your programs. We discussed how to create threads of execution using class THRead and ThreadStart delegates both from the System.Threading namespace.
      • We discussed several applications of concurrent programming. In particular, you learned about problems that may occur when multiple threads share the same data. We demonstrated how to synchronize threads using the capabilities of class Monitor to ensure that data is accessed an manipulated properly by multiple threads. We also showed how to implement shared data as a circular buffer to enable threads to operate more efficiently.

    Next, you learned that GUI components are not thread safe, so all changes to GUI components should be performed in the user interface thread that creates and maintains the GUI. We showed how to use Control method Invoke and a delegate to allow a thread to specify tasks that the user interface thread should perform on GUI components. This enabled multiple threads to modify GUI components in a thread-safe manner