当前位置:文档之家› C#学习小结(委托、全局变量、数组和枚举运用、线程)

C#学习小结(委托、全局变量、数组和枚举运用、线程)

-)C#语言

1)委托:

委托实现一般分三步骤:

1、声明委托

声明一个新的委托类型。每个委托类型都描述参数的数目和类型,以及它可以封装的方法的返回值类型。每当需要一组新的参数类型或新的返回值类型时,都必须声明一个新的委托类型。

例如:

Public delegate void ProcessBookDelegate(Book book);

2、实例化委托。

声明了委托类型后,必须创建委托对象并使之与特定方法关联。在上面的示例中,这是通过将PrintTitle 方法传递给ProcessPaperbackBooks 方法来完成的,如下所示:

static void PrintTitle(Book b)

{ System.Console.WriteLine(" {0}", b.Title); }

bookDB.ProcessPaperbackBooks(PrintTitle);

这将创建与静态方法Test.PrintTitle 关联的新委托对象。类似地,对象totaller 的非静态方法AddBookToTotal 是按如下方式传递的:

internal void AddBookToTotal(Book book)

{ countBooks += 1;

priceBooks += book.Price; }

bookDB.ProcessPaperbackBooks(totaller.AddBookToTotal);

在两个示例中,都向ProcessPaperbackBooks 方法传递了一个新的委托对象。委托一旦创建,它的关联方法就不能更改;委托对象是不可变的。

3、调用委托。

创建委托对象后,通常将委托对象传递给将调用该委托的其他代码。通过委托对象的名称(后面跟着要传递给委托的参数,括在括号内)调用委托对象。下面是委托调用的示例: processBook(b);

与本例一样,可以通过使用BeginInvoke 和EndInvoke 方法同步或异步调用委托。

2)全局变量

在很多时候,会有一些变量会在几个窗口之间传递,而这需要用到全局变量。而在C#里,没有定义全局变量的关键字,所以可以可以用下来方法来实现全局变量。

1、用静态成员来作全程变量

2、建立一个类,然后在该类中添加一个静态的成员变量,或者加一个常量也可以,然后用的时候直接对该类进行访问即可。

class Static

{

public static SerialPort ComPort;

public static ushort usInstrumentID=0;

public static Timer tmrCommunicate;

public static Boolean IsComing=false ;

public static int TimeOutCoun t=0;

}

在窗口实例类中,可以用Static.TimeOutCount这种格式调用变量。

3、C#中没有全局变量,但可以使用命名空间和静态变实现类似功能,下面的例子定义了一个用户类,初始化用户名后,在filetobase命名空间的其它类都可以获得用户名

namespace FileToBase{

public class user

{ private static string userName;

public user(string name)

{ use r Name=name;

}

public static string UserName

{

get

{

return userName;

}

}

}

3)数组和枚举运用

1、一维数组

public byte[] ValueSJSOE;//事件SOE的个数(没有实例化,和定义其个数)

public byte[] ValueSGSOE;//事故SOE的个数

private int[] eachMessHas K eyNum ={ 8,8,5,8,3,8,8,8,5,4,4,4,4,4,4,4,2};//下面读取报文中的KEY个数(定义,实例化)

//整定值写报文的KEY和Value

public byte[] LastKeyValueZDZ=new byte[11];

//系统参数和继电器的写报文的KEY和V alue

public byte[] LastKeyValueSystemParm = new byte[6];

public byte[] LastKeyValue J DQ=new byte[6];

2、交错数组

定义:

public byte[][] KEYValueJKZ;//把读取监控值的KEY和Value存在数据里

实例化:

//初始化存储各个仪表数据的数组

KEYValueJKZ=new byte[JKZNum][];//JKZNum 是一个常量

for(int i=0 ;i

{

KEYValueJKZ[i]=new byte[6]; //每个数组的头两位是KEY

}

赋值:

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

{

KEYValueJKZ[i][0] =Convert.ToByte (i + 8);

KEYValueJKZ[i][1] = 0x41;

}

注意:交错数组与二维数组的差别

若:public byte[,] KEYValueJKZ1

则KEYValueJKZ1[1,]这样用是错误的。

而可以用KEYValueJKZ[1],返回的是一个数组。

4、枚举

Public enum DataQueueTypes {AllMess,JKKGSOE,SJSOE,SGSOE,wJDQ,

wSystemParm,wZDZ};

public DataQueueTypes SendDataQueueType;

4)线程

例子:

private Thread CheckSendDataType;

CheckSendDataType = new Thread(new ThreadStart (CheckSendData));////创建一个线程,用于识别发送区的数据格式

//创建一个线程,用于识别发送区的数据格式

private void CheckSendData()

{

………….

}

5)数值处理

1、输入一串字符,判断是否是16进制,并把字符串转化为对应的数值。

//用于检测发送数据区的数据格式的过程。

private Boolean CheckGetSendData(String strSendData)

{

if (strSendData != "")

{

foreach (char chrTemp in strSend D ata) //检测数据的合法性

{

if (chrTemp == 0x20)

continue;

else if (chrTemp >= 0x30 && chrTemp <= 0x39)

continue;

else if (chrTemp >= 0x41 && chrTemp <= 0x46)

continue;

else if (chrTemp >= 0x61 && chrTemp <= 0x66)

continue;

else

{

return (false);

}

}

try

{

String[] strData = strSendData.Split(Convert.ToChar(0x20));

int index, intCount = strData.Length;

byte[] bytDataTemp = new byte[intCount];

for (index = 0; index < intCount; index++) //16进制数据的字符串长度不能超过2

{

if (strData[index].Length > 2)

{

return(false );

}

}

for (index = 0; index < intCount; index++)

{

bytDataTemp[index] = Convert.ToByte(strData[index], 16);//把字符串转化成对应的字节数组

}

bytSendData = bytDataTemp;

return (true);

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

return (false);

}

finally

{

}

}

return (false);

}

2、把收到的16进制数据转化成字符串

private string ByteArrayToHexString(byte[] data)

{

StringBuilder sb = new StringBuild e r(data.Length * 3);

foreach (byte b in data)

sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));

return sb.ToString().ToUpper();

}

3、双浮点数保留两位数

Double Temp;

String strTemp;

Temp=123.8956;

strTemp=Temp.ToString(“f2”);

4、把长度为四的数组,转化为整数;整数转化为双浮点数的算术运算;

妙数转化为日期;以一定日期格式输出日期。

public static string GetDateTime(byte[] Data)

{

long milSecond = 0;

long Second = 0;

double totalSecond = 0;

DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0);//开始日期为1970-1-1 0:0:0

for (int i = 3; i >= 0; i--)

{

milSecond <<= 8;

milSecond = milSecond ^ Data[4 + i];//转化为整数

}

if (milSecond > 1000)

milSecond = 0;

for (int i = 3; i >= 0; i--)

{

Second <<= 8;

Second =Second ^Data[i];

}

totalSecond = (double)Second + (double)(milSecond / 1000);//转化为double再除,才能保存小数后面的数。

dt = dt.AddSeconds(totalSecond);//妙数转化为日期。

return dt.ToString("yyyy年MM月dd日HH:mm:ss");//以特定的格式,输出日期

}

6)用到的控件

1、SerialPort串口控件

(1.1)以下是读取,电脑的串口特性,以供选择。

using System.IO.Ports;

private void LoadSerialPortConfiguration()

{

foreach (string s in SerialPort.GetPort Names())

{

cmbPortName.Items.Add(s);

}

foreach (string s in Enum.GetNames(typeof(Parity)))

{

cmbParity.Items.Add(s);

}

foreach (string s in Enum.GetNames(typeof(StopBits)))

{

cmbStopBits.Items.Add(s);

}

//波特率和数据位可以分别在combobox中的items手动输入。

}

(1.2)设置串口控件

(波特率,奇偶校验,数据位,停止位)设置

//设置serialPort1的串口属性

serialPort1.PortName = cmbPortName.Text;

serialPort1.BaudRate = int.Parse(cmbBaudRate.Text);

serialPort1.DataBits = int.Parse(cmbDataBits.Text);

serialPort1.Sto p Bits = (StopBits)Enum.Parse(typeof(StopBits), cmbStopBits.Text);

serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), cmbParity.Text);

//打开串口

serialPort1.Open();

(1.3)发送数据

private void btnSend_Click(object sender, EventArgs e)

{

if (bComOpen == true)

{

if (bSendHex == true)

{

if (CheckGetSendData(txtSend.Text.Trim() ) == true)

{

byte[] data=bytSendData ;

//以字节格式发送数据

intSendDataCount += data.Length;

serialPort1.Write(data, 0, data.Length);

groupBox2.Text = "发送区:发送数据成功!";

}

else

{

groupBox2.Text = "发送区:发送数据有错!";

if (chkAutoSend.Checked == true) //当定时发送时,如果数据格式错误的话,就停止定时器

{

tmrAutoSend.Enabled = false;

chkAutoSend.Checked = false;

}

}

}

else

{

//以文本格式发送数据

serialP ort1.Write(txtSend.Text);

intSendDataCount += txtSend.Text.Length;

groupBox2.Text = "发送区:发送数据成功!";

}

}

}

(1.4)接收并显示数据

串口数据的接收是一个事件,可以通过设置其接收字节数阀值属性ReceivedBytesThreshold(N),来确定当接收大于N个字节数时,产生一个接收事件。有一点很重要的是,接收事件是托管给CLT的事件池的,也就是说运行在另一个独立线程中。所以要把接收到的数据显示在串口控件上,不能直接赋值。要通过控件的触发函数(txtReceiveDataCount.Invoke(new EventHandler(delegate { 显示数据语句})))

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)

{

if (bReceiveHex == true)

{

DataReceivedEventH andler DataReceive = new DataReceivedEventHandler(this.HexDataReceive);

DataReceive();

}

else

{

DataReceivedEventHandler DataReceive = new DataReceivedEventHandler(this.TextDataReceive);

DataReceive();

}

}

private void chkRec e iveHex_CheckedChanged(object sender, EventArgs e)//事件

{

if (chkReceiveHex.Checked == true)

bReceiveHex = true;

else

bReceiveHex = false;

}

//以文本格式显示

private void TextDataReceive()

{

String strReceiveData = serialPort1.ReadExi sting();

intReceiveDataCount += strReceiveData.Length;

Log(strReceiveData);

}

//以16进制数据显示

private void HexDataReceive()

{

// Obtain the number of bytes waiting in the port's buffer

int bytes = serialPort1.BytesToRead;

// Create a byte array buffer to hold the incoming data

byte[] buffer = new byte[bytes];

intReceiveDataCount += bytes;

// Read the data from the port and store it in our buffer

serialPort1.Read(buffer, 0, bytes);

// Show the user the incoming data in hex format

Log ( ByteArrayToHexString(buffer));

}

//在接收区显示数据

private void Log(string msg)

{

if (bStopShow == false)

{

txtReceive.Invoke(new EventHandler(delegate

{

txtReceive.AppendText(msg);

txtReceive.ScrollToCaret();

}));

}

txtReceiveDataCount.Invoke(new EventHandler(delegate { txtReceiveDataCount.Text = intReceiveDataCount.ToString(); }));

txtSendDataCount.Invoke(new EventHandler(delegate { txtSendDataCount.Text = intSendDataCount.ToString(); }));

}

2、Timer控件

发送请求报文,要用到定时器定时发送,要注意的是:在发送数据时候,要先把定时器关闭,发送完数据后,再把定时器开启。以免正在发送数据时,定时器定时事件发生时去实行其他的函数,而导致没有把应该发送的数据发送出去。

Static.tmrCommunicate = new System.Timers.Timer();

Static.tmrCommunicate.Elapsed += new ElapsedEventHandler(SendData);

Static.tmrCommunic a te.Interval = 200;

private void SendData(object source, ElapsedEventArgs e)

{

if (!Static.IsComing)

{

Static.tmrCommunicate.Enabled = false; //关定时器

Static.IsComing = true;

byte[] SendDataMess;

SendDataMess = WorkMess.GetSendData();

if (SendDataMess != null)

https://www.doczj.com/doc/2c17210761.html,Port.Write(SendDataMess, 0, SendDataMess.Length);

Static.tmrCommunicate.Enabled = true; // 定时器的调用函数一定要在实行过程中,先关后开

}

else

TimeOutHandler(); //检测是否超时,若是并做处理

}

3、ListView控件

4、TabControl 控件

用程序代码选择TabControl控件的标签,

private void ToolStripMenuItemSystemParm_Click(object sender, EventArgs e) {

if (tabControlMain.Visible == false)

{

tabControlMain.Visible = true;

panelMain.Visible = false;

}

tabControlMain.SelectedIndex = 1;//选择第二个标签

}

Trackback: https://www.doczj.com/doc/2c17210761.html,/TrackBack.aspx?PostId=1328840

相关主题
文本预览
相关文档 最新文档