Multithreading in .NET Applications

原创 2003年07月21日 10:24:00
 

Multithreading in .NET Applications

创建高水平的应用程序,多线程是一个很好的设计工具,特别是那些要求与与用户互操作的程序。使用Microsoft.NET能很方便的创建这样的多线程应用程序。Part1Part2两不部分探索了NET 的框架。在第一篇中,我们讨论了线程的背景知识,线程的优点,并提供了例子。 在第二篇中,我们讨论了多线程的工作机制,以及线程同步机制。在这篇文章中(多线程的最后一篇)我们来分析和使用System.Threading,System.Net两个名字空间。

 网络编程基础<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

要是编写一个程序能回答网络请求,我们首先要了解网络组成,以及相应的技术。我不将全面的解释网络和网络的工作机制,相反,我将提供这些题目的基础知识。一些定义如下:

   TCP/IP -这是计算机用来通信的一套协议,是路由协议,这就意味着如果你的目的地主机,如果不依赖它所在地网络的话,这个路由将保证你的通信能够正常进行。

   Port-每一个基于TCP/IP协议的应用程序,都有一个唯一确定的端口。这个端口是应用程序用来通信的逻辑通道。一些端口被保留给协议使用,例如:如果你连接Web服务器,那么你将使用80端口,这端口是HTTP保留的。

Socket-一个socket就是两个应用程序的网络连接的一端。这是一种用来在同一台机器,或者网络中不同机器通信的一种机制。一个socket往往绑定在一个具体的Port上。

Listener  Application

 Listener  Application也就是服务器程序,它打开网络端口,同时等待客户机的连接。这样的程序包括web 服务器,数据库服务器,e-mail服务器,chat服务器等等。Listener Application

l         一般都遵循以下算法:

l         能打开可以使用的端口。

l         通过端口可以等待客户端Socket的连接。

l         客户端通过Socket连接,提出请求或者连接服务。

l         服务器启动一些进程发送回答。

l         关闭客户端Socket连接。

Sample Listener Code Listing

 下面的例子遵循上面提到的基本算法。它包括一个控制台应用程序,这个程序用来打开port同时等待客户的socket连接。在这里我们只是编写很简单的连接程序。一旦客户端连接上了,服务器将每隔几秒发送当前时间的数据给客户端。然后,这个listener将关闭连接,重新等待其他客户端的连接。

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.Threading;

 

namespace CodeGuru.MultithreadedPart3

{

  /// <remarks>

  /// Example console application demonstrating a listener/server

  /// application.

  /// Waits for connections to be made and responds with a message.

  /// </remarks>

  class HelloWorldServer

  {

   /// <summary>

    /// The main entry point for the application.

    /// </summary>

    [STAThread]

    static void Main(string[] args)

    {

      try

      {

        DateTime now;

        String dateStr;

 

        // Choose a port other than 8080 if you have difficulty

        TcpListener listener = new TcpListener(IPAddress.Loopback,

                                               8080);

        listener.Start();

 

        Console.WriteLine("Waiting for clients to connect");

        Console.WriteLine("Press Ctrl+c to Quit...");

        while(true)

        {

          // Accept blocks until a client connects

          Socket clientSocket = listener.AcceptSocket();

 

          for( int i = 0; i < 10; i++ )

          {

            // Get the current date and time then build a

            // Byte Array to send

            now = DateTime.Now;

            dateStr = now.ToShortDateString() + " "

                    + now.ToLongTimeString();

            Byte[] byteDateLine = Encoding.ASCII.GetBytes(

                                  dateStr.ToCharArray());

 

            // Send the data

            clientSocket.Send(byteDateLine, byteDateLine.Length, 0);

            Thread.Sleep(1000);

            Console.WriteLine("Sent {0}", dateStr);

          }

          clientSocket.Close();

        }

    }

    catch( SocketException socketEx )

      {

        Console.WriteLine("Socket error: {0}", socketEx.Message);

      }

    }

  }

}

Sample Client Code Listing

下面的代码将连接服务器,同时显示服务器发送过来的数据。

using System;

using System.IO;

using System.Net;

using System.Net.Sockets;

using System.Text;

 

namespace CodeGuru.MultithreadedPart3

{

  /// <remarks>

  /// Example console application demonstrating a client

  /// application.

  /// Makes a connection to the server and displays the response.

  /// </remarks>

  class HelloWorldClient

  {

    /// <summary>

    /// The main entry point for the application.

    /// </summary>

    [STAThread]

    static void Main(string[] args)

    {

      bool isDone = false;

      Byte[] read = new Byte[32];

      TcpClient client = new TcpClient("localhost", 8080);

 

      // Get the stream to read the input

      Stream s;

      try

      {

        s = client.GetStream();

      }

      catch( InvalidOperationException )

      {

        Console.WriteLine("Cannot connect to localhost");

        return;

      }

 

      // Read the stream and convert it to ASII

      while( !isDone )

      {

        int numBytes = s.Read(read, 0, read.Length);

        String data = Encoding.ASCII.GetString(read);

        if( numBytes == 0 )

        {

          isDone = true;

        }

        else

        {

          Console.WriteLine("Received {0} bytes: {1}",

                             numBytes, data);

        }

      }

      client.Close();

    }

  }

}

Testing the Listener Using the Client

把服务器程序和客户端程序copy到不同的位置,独立编译。打开控制台来运行服务器程序,同时打开另外一个控制台来运行客户端程序,你将看到类似以下的结果。

 

图: 1—Listener

 

 

2—Client

我们再次执行一个客户端程序,打开第三个控制台,再次执行客户端程序,你将看到这两个客户端程序只有一个能从服务器上接受到数据。另外一个在等待服务器的应答。一旦第一个客户端程序完成,第二个将接到服务器的应答。

Multithreaded Listener Application

上面的例子的问题是服务器只能在一个时刻建立一个连接。这也许在我们这个date/time例子已经足够了,但是对于其他服务器程序例如Web服务器,这是远远不行的。由于服务器的程序是单线程的,因此,它只能应答一个客户端的响应。为了应答多个客户程序同时的请求。我们必须创建不同的多个线程来处理每个请求。

Sample Listener Code Listing

下面是代码修改类前面的服务器程序,这样,它可以同时应答多个请求。在这里,我们创建一个新的线程来应答新的客户端的请求。每个客户端socket将被分配给新的HelloWorldServer实例。这样,客户端请求将可以被新线程处理。

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.Threading;

namespace CodeGuru.MultithreadedPart3

{

  /// <remarks>

  /// Example console application demonstrating a listener/server

  /// application.

  /// Waits for connections to be made and responds with a message.

  /// </remarks>

  class HelloWorldServer

  {

    // Socket to use to accept client connections

    private Socket _socket;

 

    /// <summary>

    /// The main entry point for the application.

    /// </summary>

    [STAThread]

    static void Main(string[] args)

    {

      try

      {

        TcpListener listener = new TcpListener(

                                   IPAddress.Loopback, 8080);

        listener.Start();

 

        Console.WriteLine("Waiting for clients to connect");

        Console.WriteLine("Press Ctrl+c to Quit...");

        while(true)

        {

          // Accept blocks until a client connects

          HelloWorldServer hwServer = new HelloWorldServer();

          hwServer._socket = listener.AcceptSocket();

 

          // Process the client connection on a new thread

          Thread sampleThread = new Thread(new ThreadStart(

                                           hwServer.Process));

          sampleThread.Start();

        }

      }

      catch( SocketException socketEx )

      {

        Console.WriteLine("Socket error: {0}", socketEx.Message);

      }

    }

    /*

     * Get the current date and time and send it to the client.

     * Requires that a socket is created and connected to a client.

     * Closes the socket when complete.

     */

    private void Process()

    {

      DateTime now;

      String dateStr;

 

      for( int i = 0; i < 10; i++ )

      {

        // Get the current date and time then concatenate build

        // a Byte Array to send

        now = DateTime.Now;

        dateStr = now.ToShortDateString() + " "

                + now.ToLongTimeString();

        Byte[] byteDateLine = Encoding.ASCII.GetBytes(

                                      dateStr.ToCharArray());

 

        // Send the data

        this._socket.Send(byteDateLine, byteDateLine.Length, 0);

        Thread.Sleep(1000);

        Console.WriteLine("Sent {0}", dateStr);

      }

      this._socket.Close();

    }

  }

}

Testing the Multithreaded Listener Using the Client

拷贝更新了的服务器程序代码到适当的位置,并重编译。从控制台运行服务器程序。从多个不同的控制台运行多个客户端程序,你将注意到客户端程序都能接到服务器的响应。

Possible Enhancements

上面的例子包括一个简单的服务器程序和客户端程序,你可以使用他们来作为熟悉System.net名字空间的开始。此外,你可以做以下的扩展工作:

扩展客户端程序来发送具体工作的请求。更改服务器程序来应答不同的具体工作请求。例如:

l         客户端可以发送”DATATIME”的数据作为请求,同时服务器用date和time来应答。

l         不使用控制台作为服务器,而使用windows 服务器,这样,可以自动启动,和后台运行。

 About the Author

Mark Strawmyer, MCSD, MCSE (NT4/W2K), MCDBA is a Senior Architect of .NET applications for large- and mid-size organizations. Mark is a technology leader with Crowe Chizek in Indianapolis, Indiana. He specializes in the architecture, design, and development of Microsoft-based solutions. You can reach Mark at mstrawmyer@crowechizek.com.

 

 

 

 

蓝桥杯练习系统Multithreading

#include using namespace std; typedef struct { int i; int xi; }ST; void sort(ST *thr,int n) //排序  { ...
  • huangxinfeng_
  • huangxinfeng_
  • 2016年03月02日 15:34
  • 1184

python的多进程编程(3)

翻译python2.7.10 multiporcess部分
  • u012374229
  • u012374229
  • 2015年06月17日 10:50
  • 435

第七章:MongoDB管理维护Replica Sets(读写分离&故障转移&增删节点)

一 . 读写分离 1. 登录主库: ./mongo 192.168.56.88:27017  插入一条数据:  testrs:PRIMARY> db.person.insert({"name"...
  • u012150392
  • u012150392
  • 2015年05月21日 11:51
  • 1365

python使用多进程或者多线程

使用python做计算的时候,为了加快速率,可以启用多进程或者多线程。那几时使用多进程或者多线程呢 如果是io型,使用多线程,如果是cpu型,使用多进程。 理论上说,使用多进程是效率最大的,而且i...
  • cyuanxin
  • cyuanxin
  • 2016年09月24日 13:56
  • 847

第七章:管理维护Replica Sets(读写分离&故障转移&增删节点)

   一 . 读写分离 1. 登录主库: ./mongo 192.168.56.88:27017  插入一条数据:  testrs:PRIMARY> db.person....
  • zhengwei125
  • zhengwei125
  • 2015年06月15日 11:39
  • 770

Android性能相关常用命令收集

Android性能相关常用命令收集 1.CUP (1)adb shell (进入linux的底层) (2)echo 3>/proc/sys/vm/drop_caches (清除一下系统cache...
  • u011006622
  • u011006622
  • 2017年08月02日 15:03
  • 152

Ubuntu中查找与Launcher图标所对应的命令

计算机系统:Ubuntu14.04.2 1 背景     Ubuntu系统的GUI做的比较漂亮,并且预装了许多基于GUI的系统管理工具,例如System Settings工具,Software Cen...
  • Q1302182594
  • Q1302182594
  • 2015年07月25日 19:40
  • 1478

iOS 应用内购买(In-App Purchase)之协议、税务和银行业务

iOS 应用内购买(In-App Purchase)之协议、税务和银行业务, IAP 流程好长啊
  • lxmy2012
  • lxmy2012
  • 2015年10月09日 18:03
  • 12110

Architecting HBase Applications-O'Reilly 2016(笔记)最有趣的部分就是Key如何设计了

Architecting HBase Applications 目录 1 What is HBase?2 HBase原则3 HBase生态系统4 Siz...
  • cteng
  • cteng
  • 2016年08月09日 20:56
  • 810

通过Blueprint进行模块化的Flask应用开发[转]

转载 转自: http://note.costony.com/article/modular-applications-with-blueprints-in-flask ...
  • u010002387
  • u010002387
  • 2015年01月07日 19:34
  • 543
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Multithreading in .NET Applications
举报原因:
原因补充:

(最多只允许输入30个字)