博文

c#中ref和out参数使用时需要注意的问题(2006-05-31 16:56:00)

摘要:昨天写了个关于socket接收udp包的程序,调用了socket.ReceiveFrom方法,发现了一个c#中关于ref和out参数传递时的问题,这里提出来和大家共同探讨一下,首先声明,下面的结论都是本人推测,还没有得到任何定论,若有错误请大家指正。 首先,ReceiveFrom方法的原型为        public int ReceiveFrom(byte[], ref EndPoint); 有一个为ref的EndPoint参数,用它来返回收到包的源地址信息,ref的语义是传引用,即对所传引用的修改可以反映到方法外面。我一般都使用IPEndPoint来表示地址信息,所以很自然的使用了如下的调用方法        (代码1)        IPEndPoint iep = new IPEndPoint(IPAddress.Any,0);        socket.ReceiveFrom(buffer,ref  (EndPoint)iep); 这时编译时出现了一下的错误,“ref或out参数必须是一个lvalue”,iep怎么会不是一个左值呢?关键是在调用方法时使用的强制转换(例如(EndPoint)iep),我改了一下代码        (代码2) IPEndPoint iep = new IPEndPoint(IPAddress.Any,0);        EndPoint ep = (EndPoint)iep;        socket.ReceiveFrom(buffer,ref  (EndPoint)iep); 这次通过编译了。为什么在方法调用时会出问题?这里要考虑类型强制转换时的一个细节,强制转换时编译器会先生成一个临时引用,然后再把这个临时引用传给一个和转换类型相同的引用,这个临时引用比......

阅读全文(1873) | 评论:0

C#数据库连接字符大全(2006-05-31 16:49:00)

摘要:   SQL Server  ODBC

 Standard Security:
"Driver={SQL Server};Server=Aron1;Database=pubs;Uid=sa;Pwd=asdasd;"

 Trusted connection:
"Driver={SQL Server};Server=Aron1;Database=pubs;Trusted_Connection=yes;"

 Prompt for username and password:
oConn.Properties("Prompt") = adPromptAlways
oConn.Open "Driver={SQL Server};Server=Aron1;DataBase=pubs;"

 OLE DB, OleDbConnection (.net)

 Standard Security:
"Provider=sqloledb;Data Source=Aron1;Initial Catalog=pubs;User Id=sa;Password=asdasd;"

 Trusted Connection:
"Provider=sqloledb;Data Source=Aron1;Initial Catalog=pubs;Integrated Security=SSPI;" (use serverName\instanceName as Data Source to use an specifik SQLServer instance, only SQLServer2000)  Prompt for username and password:
oConn.Provider = "sqloledb"
oConn.Properties("Prompt") = adPromptAlways
oConn.Open "Data Source=Aron1;Initial Cata......

阅读全文(2242) | 评论:0

关于SQLSERVER数据操作的常用类库(2006-05-31 16:25:00)

摘要:  根据自己平时的经验写的针对SQLSERVER操作的通用类库
using System;
using System.Data;
using System.Data.SqlClient;
using System.Web;

namespace Whgw_lc
{
/// <summary>
/// Data 的摘要说明。
/// </summary>
/// <summary>
/// 数据库相关操作类
/// 作者:DarkAngel
/// 时间:2004-9-24
/// </summary>
public class Data
{
/// <summary>
///连接数据库字符串
/// </summary>
protected static string con="data source=10.68.19.203;initial catalog=Whgw;persist security info=False;user id=sa;password=sc2000;workstation id=DARKANGEL;packet size=4096";
/// <summary>
/// 数据库连接对象
/// </summary>
protected System.Data .SqlClient.SqlConnection DataConnection;
/// <summary>
/// SqlDataAdapter对象
/// </summary>
protected System.Data.SqlClient.SqlDataAdapter DataAdapter;
/// <summary>
/// SqlCommand对象
/// </summary>
protected System.Dat......

阅读全文(1759) | 评论:0

用C#给程序加启动画面并只允许一个应用程序实例运行(2006-05-31 16:20:00)

摘要:1、   启动画面类:      public class SplashForm : System.Windows.Forms.Form      {          private System.Windows.Forms.PictureBox pictureBox1;          private System.Windows.Forms.Label label1;          private System.Windows.Forms.Label lbl_version;          /// <summary>          /// 必需的设计器变量。          /// </summary>           private System.ComponentModel.Container components = null;            public SplashForm()          {               //         &......

阅读全文(1672) | 评论:0

C#的多线程(2)——机制探索 互斥对象——更加灵活的同步方式(2006-05-30 14:58:00)

摘要:5、互斥对象——更加灵活的同步方式

  有 时候你会觉得上面介绍的方法好像不够用,对,我们解决了代码和资源的同步问题,解决了多线程自动化管理和定时触发的问题,但是如何控制多个线程相互之间的 联系呢?例如我要到餐厅吃饭,在吃饭之前我先得等待厨师把饭菜做好,之后我开始吃饭,吃完我还得付款,付款方式可以是现金,也可以是信用卡,付款之后我才 能离开。分析一下这个过程,我吃饭可以看作是主线程,厨师做饭又是一个线程,服务员用信用卡收款和收现金可以看作另外两个线程,大家可以很清楚地看到其中 的关系——我吃饭必须等待厨师做饭,然后等待两个收款线程之中任意一个的完成,然后我吃饭这个线程可以执行离开这个步骤,于是我吃饭才算结束了。事实上,现实中有着比这更复杂的联系,我们怎样才能很好地控制它们而不产生冲突和重复呢?

  这种情况下,我们需要用到互斥对象,即System.Threading命名空间中的Mutex类。大家一定坐过出租车吧,事实上我们可以把Mutex看作一个出租车,那么乘客就是线程了,乘客首先得等车,然后上车,最后下车,当一个乘客在车上时,其他乘客就只有等他下车以后才可以上车。而线程与Mutex对象的关系也正是如此,线程使用Mutex.WaitOne()方法等待Mutex对象被释放,如果它等待的Mutex对象被释放了,它就自动拥有这个对象,直到它调用Mutex.ReleaseMutex()方法释放这个对象,而在此期间,其他想要获取这个Mutex对象的线程都只有等待。

  下面这个例子使用了Mutex对象来同步四个线程,主线程等待四个线程的结束,而这四个线程的运行又是与两个Mutex对象相关联的。其中还用到AutoResetEvent类的对象,如同上面提到的ManualResetEvent对象一样,大家可以把它简单地理解为一个信号灯,使用AutoResetEvent.Set()方法可以设置它为有信号状态,而使用AutoResetEvent.Reset()方法把它设置为无信号状态。这里用它的有信号状态来表示一个线程的结束。
  // Mutex.cs
  using System;
  using System.Threading;

  public class MutexSample

阅读全文(2628) | 评论:0

C#的多线程(2)——机制探索 线程池和定时器——多线程的自动管理 (2006-05-30 14:58:00)

摘要:四、线程池和定时器——多线程的自动管理
  在多线程的程序中,经常会出现两种情况。一种情况下,应用程序中的线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应;而另外一种情况则是线程平常都处于休眠状态,只是周期性地被唤醒。在.net framework里边,我们使用ThreadPool来对付第一种情况,使用Timer来对付第二种情况。

  ThreadPool类提供一个由系统维护的线程池——可以看作一个线程的容器,该容器需要Windows 2000以上版本的系统支持,因为其中某些方法调用了只有高版本的Windows才有的API函数。你可以使用ThreadPool.QueueUserWorkItem()方法将线程安放在线程池里,该方法的原型如下:

  //将一个线程放进线程池,该线程的Start()方法将调用WaitCallback代理对象代表的函数
  public static bool QueueUserWorkItem(WaitCallback);
  //重载的方法如下,参数object将传递给WaitCallback所代表的方法
  public static bool QueueUserWorkItem(WaitCallback, object);


  要注意的是,ThreadPool类也是一个静态类,你不能也不必要生成它的对象,而且一旦使用该方法在线程池中添加了一个项目,那么该项目将是没有办法取消的。在这里你无需自己建立线程,只需把你要做的工作写成函数,然后作为参数传递给ThreadPool.QueueUserWorkItem()方法就行了,传递的方法就是依靠WaitCallback代理对象,而线程的建立、管理、运行等等工作都是由系统自动完成的,你无须考虑那些复杂的细节问题,线程池的优点也就在这里体现出来了,就好像你是公司老板——只需要安排工作,而不必亲自动手。 下面的例程演示了ThreadPool的用法。首先程序创建了一个ManualResetEvent对象,该对象就像一个信号灯,可以利用它的信号来通知其它线程,本例中当线程池中所有线程工作都完成以后,ManualResetEvent的对象将被设置为有信号,从而通知主线程继续运行。它有几个重要的方法:Rese......

阅读全文(4634) | 评论:0

C#的多线程(2)——机制探索  线程的同步和通讯——生产者和消费者 (2006-05-30 14:56:00)

摘要:三.线程的同步和通讯——生产者和消费者

  假 设这样一种情况,两个线程同时维护一个队列,如果一个线程对队列中添加元素,而另外一个线程从队列中取用元素,那么我们称添加元素的线程为生产者,称取用 元素的线程为消费者。生产者与消费者问题看起来很简单,但是却是多线程应用中一个必须解决的问题,它涉及到线程之间的同步和通讯问题。

  前面说过,每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数。但是多线程环境下,可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生。C#提供了一个关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待。在C#中,关键字lock定义如下:

  lock(expression) statement_block expression代表你希望跟踪的对象,通常是对象引用。一般地,如果你想保护一个类的实例,你可以使用this;如果你希望保护一个静态变量(如互斥代码段在一个静态方法内部),一般使用类名就可以了。而statement_block就是互斥段的代码,这段代码在一个时刻内只可能被一个线程执行。

  下面是一个使用lock关键字的典型例子,我将在注释里向大家说明lock关键字的用法和用途:   //lock.cs
  using System;
  using System.Threading;

  internal class Account
  {
  int balance;
  Random r = new Random();
  internal Account(int initial)
  {
    balance = initial;
  }

  internal int Withdraw(int amount)
  {
    if (balance < 0)
    {
    file://如果balance小于0则抛出异常
   ......

阅读全文(2800) | 评论:0

C#的多线程(2)——机制探索 操纵一个线程(2006-05-30 14:55:00)

摘要:二.操纵一个线程

  任何程序在执行时,至少有一个主线程,下面这段小程序可以给读者一个直观的印象: //SystemThread.cs
using System;
using System.Threading;

namespace ThreadTest
{
  class RunIt
  {
    [STAThread]
    static void Main(string[] args)
    {
      Thread.CurrentThread.Name="System Thread";//给当前线程起名为"System Thread"
Console.WriteLine(Thread.CurrentThread.Name+"''''Status:"+Thread.CurrentThread.ThreadState);
      Console.ReadLine();
    }
  }
}
  编译执行后你看到了什么?是的,程序将产生如下输出:

  System Thread''''s Status:Running

  在这里,我们通过Thread类的静态属性CurrentThread获取了当前执行的线程,对其Name属性赋值“System Thread”,最后还输出了它的当前状态(ThreadState)。所谓静态属性,就是这个类所有对象所公有的属性,不管你创建了多少个这个类的实例,但是类的静态属性在内存中只有一个。很容易理解CurrentThread为什么是静态的——虽然有多个线程同时存在,但是在某一个时刻,CPU只能执行其中一个。

  就像上面程序所演示的,我们通过Thread类来创建和控制线程。注意到程序的头部,我们使用了如下命名空间:   using System;
  using System.Threading;
  在.net framework class library中,所有与多线程机制应用相关的类都是放在System.Threading命名空间中的。其中提供Thread类用于创建线程,ThreadP......

阅读全文(2888) | 评论:0

C#的多线程(2)——机制探索 多线程的概念(2006-05-30 14:54:00)

摘要:注:本文中出现的代码均在.net Framework RC3环境中运行通过

  一.多线程的概念

  Windows是一个多任务的系统,如果你使用的是windows 2000及 其以上版本,你可以通过任务管理器查看当前系统运行的程序和进程。什么是进程呢?当一个程序开始运行时,它就是一个进程,进程所指包括运行中的程序和程序 所使用到的内存和系统资源。而一个进程又是由多个线程所组成的,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。浏览器就是一个很好的多线程的例子,在浏览器中你可以在下载JAVA小应用程序或图象的同时滚动页面,在访问新页面时,播放动画和声音,打印文件等。

  多线程的好处在于可以提高CPU的利用率——任何一个程序员都不希望自己的程序很多时候没事可干,在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。

  然而我们也必须认识到线程本身可能影响系统性能的不利方面,以正确使用线程: 线程也是程序,所以线程需要占用内存,线程越多占用内存也越多 多线程需要协调和管理,所以需要CPU时间跟踪线程 线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题 线程太多会导致控制太复杂,最终可能造成很多Bug   基 于以上认识,我们可以一个比喻来加深理解。假设有一个公司,公司里有很多各司其职的职员,那么我们可以认为这个正常运作的公司就是一个进程,而公司里的职 员就是线程。一个公司至少得有一个职员吧,同理,一个进程至少包含一个线程。在公司里,你可以一个职员干所有的事,但是效率很显然是高不起来的,一个人的 公司也不可能做大;一个程序中也可以只用一个线程去做事,事实上,一些过时的语言如fortune,basic都是如此,但是象一个人的公司一样,效率很低,如果做大程序,效率更低——事实上现在几乎没有单线程的商业软件。公司的职员越多,老板就得发越多的薪水给他们,还得耗费大量精力去管理他们,协调他们之间的矛盾和......

阅读全文(2021) | 评论:0

使用 Mutex 对象提供对资源的独占访问(MSDN)(2006-05-30 13:22:00)

摘要:可以使用 Mutex 对象提供对资源的独占访问。Mutex 类比 Monitor 类使用更多系统资源,但是它可以跨应用程序域边界进行封送处理,可用于多个等待,并且可用于同步不同进程中的线程。有关托管同步机制的比较,请参见同步基元概述。 有关代码示例,请参见 Mutex 构造函数的参考文档。 使用 Mutex 线程调用 mutex 的 WaitOne 方法请求所有权。该调用会一直阻塞到 mutex 可用,或直至达到可选的超时间隔。如果没有任何线程拥有它,则 Mutex 的状态为已发信号的状态。 线程通过调用其 ReleaseMutex 方法释放 mutex。mutex 具有线程关联;即 mutex 只能由拥有它的线程释放。如果线程释放不是它拥有的 mutex,则会在该线程中引发 ApplicationException。 由于 Mutex 类从 WaitHandle 派生,所以您还可以结合其他等待句柄调用 WaitHandle 的静态 WaitAll 或 WaitAny 方法请求 Mutex 的所有权。 如果某个线程拥有 Mutex,则该线程就可以在重复的等待-请求调用中指定同一个 Mutex,而不必阻止其执行;但是,它必须释放 Mutex,次数与释放所属权的次数相同。 被放弃的 mutex 如果线程终止而未释放 Mutex,则认为该 mutex 已放弃。这是严重的编程错误,因为该 mutex 正在保护的资源可能会处于不一致的状态。在 .NET Framework 2.0 版中,获取该 mutex 的下一个线程中将引发 AbandonedMutexException。 注意 在 .NET Framework 1.0 和 1.1 版中,放弃的 Mutex 被设置为已发送信号状态,下一个等待线程将获得所有权。如果没有等待线程,则 Mutex 保持已发送信号状态。不引发异常。 本地 mutex 和系统 mutex Mutex 分两种类型:本地 mutex 和命名系统 mutex。如果使用接受名称的构造函数创建了 Mutex 对象,那么该对象将与具有该名称的操作系统对象相关联。命名的系统 mutex 在整个操作系统中都可见,并且可用于同步进程活动。您可以创建多个 Mutex 对象来表示同一命名系统 mutex,而......

阅读全文(4446) | 评论:0