.NET新手系列(九)

没怎么整理,乱得很,姑且如此吧...-_-

1.遇到的问题:

Mysql中编写SQL语句以及MYSQL-FRONT

解决方法:

学过SQL SERVERMYSQL的语法有些不同。

1)创建存储过程语句,括号是必须的,存储过程的参数必须写在括号里。语句块的开始和结束处要分别用BEGINEND,当然还要记住最基本的分号。

另外,存储过程的调用语句要用CALL

如果有输出参数,则OUT关键字一定要在参数名前。

create PROCEDURE sp1()

begin

declare uvcount int;

select COUNT(*) into uvcount from mytable1;

select uvcount;

end;

 

call sp1();

 

drop PROCEDURE sp1;

 

create procedure sp4(out pcount int)

……

call sp4(@a);

SELECT @a;

 

 

2)LIMIT语法,可以带一个参数,也可以带两个参数,可用于数据的分页,如下:

select * from employees limit 5;//只选出5

 

select * from employees order by employeeid desc limit 5,10;//选出第5行之后的10行,

 

SELECT * from employees where employeeid IN(

select employeeid from employees order by employeeid desc LIMIT 5)

limit 3;//语法错误,limit无法嵌套使用

 

 

3)MYSQL中的自增列,用AUTO_INCREMENT关键字表示,同时,自增列一定要声明为主键,否则错误。

另外,主键的声明可以在某列之后直接声明,也可以另起一行声明,如下:

CREATE TABLE animals (

     id INT NOT NULL AUTO_INCREMENT,

     name CHAR(30) NOT NULL,

     PRIMARY KEY (id)

 );

 

CREATE TABLE animals (

     id INT PRIMARY KEY

     name CHAR(30)

);

 

 

4)外键声明语法:

create table mytable4(

fid int,

fname char(8),

foreign key(fid) references mytable1(fid)

);

 

 

5)关于MYSQL中的字符串,字符串可以用单引号或双引号标识出:

A string is a sequence of characters, surrounded by either single quote (‘'’) or double quote (‘"’) characters. Examples:

'a string'

"another string"

 

There are several ways to include quotes within a string:

A ‘'’ inside a string quoted with ‘'’ may be written as ‘''’.

A ‘"’ inside a string quoted with ‘"’ may be written as ‘""’.

You can precede the quote character with an escape character (‘\’).

A ‘'’ inside a string quoted with ‘"’ needs no special treatment and need not be doubled or escaped. In the same way, ‘"’ inside a string quoted with ‘'’ needs no special treatment.

 

 

6)默认值的语法:

create table mytable4(

fid int,

fname char(10),

fdefault char(10) default "aaa"

);

 

 

7)MYSQL里如何设置某列的默认值为当前系统时间

关于字段的默认值,MYSQL有如下规定:

如果一个字段没有明确定义DEFAULT值,MySQL将会为这个字段自动地添加一个。

如果这个字段允许接受NULL值,那么该字段的默认值为NULL

如果一个字段被定义为NOT  NULL,那么它的默认值将取决于该字段类型:

1、数值类型的字段(除定义了AUTO_INCREMENT属性),默认值为0

而一个AUTO_INCREMENT的字段,默认值是它的序列的下一个数值。

2、日期和时间类型的字段(TIMESTAMP),它的默认值是适当形式的0

表中的第一个TIMESTAMP字段,它的默认值为当前日期和时间。

3、字符串类型字段(ENUM),它的默认值是一个空串。

ENUM类型的字段,默认值为第一个枚举值(如果你没有明确地使用DEFAULT指定其它的默认值)

 

ORACLE里的SYSDATEMSSQL中的GETDATE(),MYSQL里也有CURDATE()CURTIME()NOW()一类的时间日期函数,但是如上所述,到目前版本为止,MYSQL不允许以函数或表达式作为某一列的默认值,即默认值必须为一个常数。

 

要达到你某列的默认值为当前更新日期与时间的功能,某些情况下,你可以使用TIMESTAMP列类型实现:

 

TIMESTAMP值可以从1970的某时的开始一直到2037年,精度为一秒,其值作为数字显示。“完整”的TIMESTAMP格式是14位,常见的显示尺寸是6812、和14

然而,虽然你建表时可以定义列为TIMESTAMP(8),但在你进行数据插入与更新时TIMESTAMP列实际上保存了14位的数据(包括年月日时分秒),只不过在你进行查询时MySQL返回给你的是8位的年月日数据。

同时,不合法TIMESTAMP值被变换到适当类型的“零”值(00000000000000)。也即在1970年到2037年之外的时间,会被强制为0,所以说只在某些情况下可用。       

 

你可以使用TIMESTAMP列类型来实现某列的默认值为当前更新日期与时间的功能,但是,如果你有多个TIMESTAMP列,只有第一个自动更新为当前时间。除第一个以外的TIMESTAMP列也可以设置到当前的日期和时间,只是须在插入时显式为列插入NULL,或NOW(),如下:

 

CREATE TABLE test (

'id' INT (3) UNSIGNED AUTO_INCREMENT,

'date1' TIMESTAMP (14),

'date2' TIMESTAMP (14),

PRIMARY KEY('id')

);

 

INSERT INTO test (id, date1, date2) VALUES (1, NULL, NULL);

INSERT INTO test SET id= 2;

结果:

1

20021114093723

20021114093723

2

20021114093724

00000000000000

 

 

8)CREATE OR REPLACE

创建视图时可以使用CREATE OR REPLACE语句,建表或创建存储过程时不能作用该语句,只能使用:DROP TABLE(PROCEDURE) IF EXIST ……语句,语句如下:

 

CREATE  OR  REPLACE  VIEW  view2

AS

SELECT * FROM mytable1 WHERE fid=1;

 

 

10)如何获取最新插入的自增列的值

select last_insert_id();

select @@session.identity;

两种方法都可以获得最后插入的自增列的值

 

 

10)如何连接字符串:

使用CONCAT()

 

 

 

2.遇到的问题:

MySQL中的数据类型之于SQL Server中的数据类型

解决方法:

SQL Server

Mysql

int

int(11)

char

char

bigint

bigint(20)

binary

binary

bit

bit(1)

datetime

datetime

decimal

decimal

float

double

image

mediumblob

money

decimal(19,4)

nchar

char

ntext

mediumtext

numeric

decimal

nvarchar

varchar

real

float

smalldatetime

datetime

smallint

smallint(6)

smallmoney

decimal(10,4)

sql_variant

mediumblob

text

mediumtext

timestamp

binary(8)

tinyint

tinyint(3)

uniqueidentifier

mediumblob

varbinary

tinyblob

varchar

varchar

 

Another extension is supported by MySQL for optionally specifying the display width of an integer value in parentheses following the base keyword for the type (for example, INT(4)). This optional display width specification is used to left-pad the display of values having a width less than the width specified for the column.

 

The display width does not constrain the range of values that can be stored in the column, nor the number of digits that are displayed for values having a width exceeding that specified for the column.

 

When used in conjunction with the optional extension attribute ZEROFILL, the default padding of spaces is replaced with zeros. For example, for a column declared as INT(5) ZEROFILL, a value of 4 is retrieved as 00004. Note that if you store larger values than the display width in an integer column, you may experience problems when MySQL generates temporary tables for some complicated joins, because in these cases MySQL trusts that the data did fit into the original column width.

(如果数值较小,则用0左填充到指定的位数,不知道这么做有什么意义?还是我理解有误?)

 

 

 

3.遇到的问题:

SQL Server中导出SQL语句中的一些细节:

解决方法:

前几天从SQL SERVER中导出一堆的SQL语句,其中的一些不太理解,自已查了一下:

1)   字符串的N前缀:

IF EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = N'myDB')

DROP DATABASE [myhuang1]

GO

数据库名“myDB”前加了一个字母N做前缀

Unicode 常量使用 N 开头来指定:N'A Unicode string',参见联机丛书的“使用unicode数据”。

 

使用 Unicode 数据类型来表示和存储字符数据可以避免在不同的语言编码环境中移植时出现的问题。这意味着您应该使用 nchar 来代替 char,使用 nvarchar 来代替 varchar,以及使用 ntext 来代替 text。尽管使用 Unicode 数据类型会在可存储的字符串的长度方面有所限制,并且可能比使用非 Unicode 类型稍微慢一些和麻烦一些。

 

按照联机图书主题“使用 Unicode 数据”中所规定的那样,在 Unicode 字符串常量前面加上一个大写字母 N 前缀,不这样做将导致 SQL Server 在使用相应的字符串之前将其转换为当前数据库的非 Unicode 代码页。下面是一个示例:

-- Assumes the default code page is not Greek

create table #t1 (c1 nchar(1))

 

insert #t1 values(N'Ω')

insert #t1 values('Ω')

 

select * from #t1

 

这将返回:

 

c1

----

Ω

O

 

两个 insert 语句都试图将单个字符(希腊字母Ω)插入到表中。在第一行的 insert 中没有数据丢失。然而,在第二行中,Ω已经被转换为不同的字符(一个大写的 O),这是因为在第二个 INSERT 语句中缺少 N 前缀,从而导致字符串被转换为默认的代码页,而在该代码页中不存在Ω(大写的 O 是最近似的字符)。

 

尽管该表的列声明使用 Unicode 数据类型,仍然不能防止数据丢失。发生数据丢失的原因是在源数据中省略了大写 N 前缀,因而 SQL Server 在插入源数据之前将其转换为默认代码页。对于日期值,如果您将采用 Unicode 参数的查询作为 RPC 事件提交,则可以缓解通过 N 前缀来区分 Unicode 字符串和非 Unicode 字符串的需要 RPC 参数本身就可以向服务器定义其数据类型。

 

2)   排序规则:

CREATE DATABASE [myDB]  ON (NAME = N'myDB_Data', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL\data\myDB_Data.MDF' , SIZE = 1, FILEGROWTH = 10%) LOG ON (NAME = N'myDB_Log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL\data\myDB_Log.LDF' , SIZE = 1, FILEGROWTH = 10%)

COLLATE Chinese_PRC_CI_AS

GO

在查询分析器内执行下面语句,可以得到SQL SERVER支持的所有排序规则。

select * from ::fn_helpcollations()

排序规则名称由两部份构成,前半部份是指本排序规则所支持的字符集。

如:

Chinese_PRC_CS_AI_WS

前半部份:指UNICODE字符集,Chinese_PRC_指针对大陆简体字UNICODE的排序规则。

排序规则的后半部份即后缀含义:

_BIN 二进制排序

_CI(CS) 是否区分大小写,CI不区分,CS区分

_AI(AS) 是否区分重音,AI不区分,AS区分

_KI(KS) 是否区分假名类型,KI不区分,KS区分

_WI(WS) 是否区分宽度 WI不区分,WS区分

 

区分大小写:如果想让比较将大写字母和小写字母视为不等,请选择该选项。

区分重音:如果想让比较将重音和非重音字母视为不等,请选择该选项。如果选择该选项,

         比较还将重音不同的字母视为不等。

区分假名:如果想让比较将片假名和平假名日语音节视为不等,请选择该选项。

区分宽度:如果想让比较将半角字符和全角字符视为不等,请选择该选项

 

3sp_dboption

exec sp_dboption N'myDB', N'autoclose', N'true'

GO

exec sp_dboption N'myDB', N'bulkcopy', N'false'

GO

exec sp_dboption N'myDB', N'trunc. log', N'true'

GO

……

在创建数据库的语句后面会有若干个 exec sp_dboption语句,是对数据库某些选项的一些设置,如第一个的意思是:当为 true 时,数据库完全关闭,其资源在最后一个用户注销后释放。

详细可以在联机丛书中的“sp_dboption”项。

 

4object_idOBJECTPROPERTY

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[test1]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)

drop table [dbo].[test1]

GO

object_id返回数据库对象标识号。

sysobjects表位于master库中,其中包含sql server中所有对象的信息,包括表、存储过程等等,其中id是一个int型的唯一标志。

OBJECTPROPERTY:返回当前数据库中对象的有关信息。

IsUserTable:判断该对象是否是用户定义的表

 

5ON [PRIMARY]

CREATE TABLE [dbo].[test1] (

         [fid] [int] NULL ,

         [fname] [char] (10) COLLATE Chinese_PRC_CI_AS NULL

) ON [PRIMARY]

GO

 

CREATE TABLE的语法中有这样一句可选语法项目:

[ ON { filegroup | DEFAULT } ]

用来指定存储表的文件组。

如果指定 filegroup,则表将存储在指定的文件组中。数据库中必须存在该文件组。如果指定 DEFAULT,或者根本未指定 ON 参数,则表存储在默认文件组中。

DEFAULT 并不是关键字。DEFAULT 是默认文件组的标识符并需对其进行定界,如 ON "DEFAULT"ON [DEFAULT]。)

ON [PRIMARY]是表示表是建立在主文件组上。PRIMARY表示主文件组。如果没有指定默认文件组,则主文件组是默认文件组,ON [PRIMARY]也可以省略掉了。

(关于文件组的概念,没有找到说的很明白的)

sysfilegroups也存在于master库中,数据库属性项中也有文件组的指定

 

6SET QUOTED_IDENTIFIER

SET QUOTED_IDENTIFIER是用于分隔标识符的设置:

分隔标识符在下列情况下使用:

当在对象名称或对象名称的组成部分中使用保留字时。

当使用未被列为合法标识符的字符时。

分隔符仅用于标识符。

 

QUOTED_IDENTIFIER ON 时,对于 SQL 语句中的双引号和单引号 (') 的使用,SQL Server 遵循 SQL-92 规则:

双引号只能用于分隔标识符,不能用于分隔字符串。 

单引号必须用来包含字符串,不能用于分隔标识符。

如果字符串包含单引号,则需要在单引号前再增加一个单引号:

 

QUOTED_IDENTIFIER OFF 时,对于双引号和单引号的使用,SQL Server 遵循如下规则:

引号不能用于分隔标识符,而是用括号作为分隔符。

单引号或双引号可用于包含字符串。

如果使用双引号,嵌入的单引号不需要用两个单引号来表示

(联机丛书)

 

7SET ANSI_NULLS

SET ANSI_NULLS ON 时,如果比较中有一个或多个表达式为 NULL,则既不输出 TRUE 也不输出 FALSE,而是输出 UNKNOWN

通过设置 ANSI_NULLS OFF 可将该选项激活。当 ANSI_NULLS OFF 时,如果 ColumnA 包含空值,则比较操作 ColumnA = NULL 返回 TRUE;如果 ColumnA 除包含 NULL 外还包含某些值,则比较操作返回 FALSE。此外,两个都取空值的表达式的比较也输出 TRUE。当 ANSI_NULLS 设置为 OFF 时,SELECT 语句将返回 Customer 表中所有 Region 为空值的行:

 

SELECT CustomerID, CompanyName, Region

FROM Northwind.dbo.Customers

WHERE Region = NULL

 

不论 ANSI_NULLS 如何设置,对于 ORDER BYGROUP BY DISTINCT 关键字空值总被视为是相等的。此外,允许 NULL 的唯一索引或 UNIQUE 约束只能包含一个带有 NULL 键值的行。后面带有 NULL 的行将被拒绝。属于主键的任何列中都不能含有 NULL

 

涉及 NULL 的计算均取值为 NULL,这是因为只要有一个因子为未知,结果肯定是 UNKNOWN。例如,如果 column1 NULL,则 column1 + 1 取值为 NULL

(联机丛书)

 

8)关于GO语句:

在查询分析器中可以使用GO语句。在程序中使用SQL语句操作数据库时,应该将GO语句删去,否则将会引起错误。

 

9)关于“XXX必须是批查询中的第一条语句”错误:

执行一堆SQL语句时,可能会遇到如下的错误,例如提示:“'CREATE PROCEDURE' 必须是批查询中的第一条语句”

SQL SERVER中,ALTER VIEWCREATE PROCEDURECREATE VIEW必须是批查询中的第一条语句,也就是在这些语句之前不能有其他语句,如果有,只好用EXEC来执行ALTER VIEWCREATE PROCEDURECREATE VIEW这些语句的字符串了。

 

 

4.遇到的问题:

关于windows应用程序窗体间数据交互

解决方法:

1)       使用带参数的构造函数。

由于新打开的窗体是通过执行构造器来生成的,因此可以在新窗口中重载构造器,使其能接收你要传递的对象。

在此过程中,需要注意show()showdialog()方法的区别:

Show()打开一个普通窗体,showdialog()打开一个模式窗体,后者打开新窗体后,除非关闭新窗体,否则焦点永远在新窗体上。

另外,show()方法在完成之后,将立即返回执行主窗体中show()方法之后的代码,而子窗体关闭时不返回执行主窗体中剩下的代码;而showdialog()方法则只有在新窗体退出之后才返回主窗体执行showdialog()方法之后的代码。比较下面代码:

A

        private void button1_Click(object sender, EventArgs e)

        {

            Form2 f2 = new Form2(this.arraylist);

            f2.Show();

 

            this.listBox1.DataSource = null;

            this.listBox1.DataSource = this.al;

        }

B

        private void button1_Click(object sender, EventArgs e)

        {

            Form2 f2 = new Form2(this.arraylist);

            f2. ShowDialog();

 

            this.listBox1.DataSource = null;

            this.listBox1.DataSource = this.al;

        }

Form2中对传入的arraylist进行改动后,关闭Form2,此时代码B中将接着执行对listbox的绑定工作,所以主窗体中的listbox将被更新。而代码A中在show()之后马上执行了对listbox的操作,而不是在Form2arraylist做出修改之后,所以当关闭Form2后,listbox未能更新。

 

除此之外,还有一个Owner属性,

f2.Owner = this;

f2.Show ();

效果是主窗体可以获得焦点,但子窗体永远显示在主窗体上一层。

 

2)      为窗体添加属性

A:为主窗体Form1添加属性。在show之前,指定Form2ownerForm1,则在Form2的代码中,可以操作Form1的属性:

private void Form2_Load(object sender, System.EventArgs e)  

{

Form1 f1 = (Form1)this.Owner;

This.al = pareForm.arraylist;

foreach(object o in this.al)

this.listBox1.Items.Add(o);

}

其中arraylistForm1的一个属性,而alForm2的字段或属性。

 

B:或者:

为子窗体添加属性,则在主窗体Form1的代码中可以写成:

Form2 f2 = new Form2();

F2.al = this.arraylist;

F2.ShowDialog();

 

3)       使用静态属性

Form1Form2之外声明一个类,在类中声明一个静态属性,Form1Form2同时使用该属性。

 

 

 

5.遇到的问题:

关于OPENFILEDIALOG等控件的筛选器

解决方法:

OPENFILEDIALOG等控件中,有时会用到筛选器。

筛选器字符串必须包含筛选器的说明,后跟竖线和筛选模式。不同筛选选项的字符串还必须以竖线分隔。例如:

“文本文件(*.txt)|*.txt|所有文件(*.*)|*.*

示例:

列出文本文件,或者列出.sql文件

this.openFileDialog1.Filter = "文本文件(*.txt)|*.txt|SQL文件(*.sql)|*.sql";

列出文本文件和.sql文件

this.openFileDialog1.Filter = "文本文件或SQL文件(*.txt,*.sql)|*.txt;*.sql";

另外,filter的设置一定要在show之前写,否则不起作用。 

 

 

6.遇到的问题:

2005中关于在GridView DataFormatString属性

解决方法

要使用GridView中类似DataFormatString="{0:yyyy-MM-dd}"  的属性设置起作用,应修改 HtmlEncode="False"才行。

网上的解释是如果HtmlEncodetrue的话,格式设置字符串的内容将被作为普通的字符串而失去功能。

 

 

 

7.遇到的问题:

关于C#MD5加密算法的简单使用示例

解决方法:

String result = "";

string s = ……;

MD5 md5 = new MD5CryptoServiceProvider();//MD5类是抽象基类

byte[] c = System.Text.Encoding.Default.GetBytes(s);

byte[] md5c = md5.ComputeHash(c);

for (int i = 0; i < md5c.Length - 1; i++)

{

     result += md5c[i].ToString("x").PadLeft(2, '0');

}

 

另:

关于ToString方法所用的格式化参数:

cC:货币格式

dD:十进制格式

eE:科学计数(指数)格式

fF:固定点格式

gG:常规格式

nN:数字格式

rR:往返格式,这确保将已转换成字符串的数字转换回数字时具有与原数字相同的值。

xX:十六进制格式

详细可参见MSDN中关于NumberFormatInfo 类、DateTimeFormatInfo 类的描述。

 

 

 

8.遇到的问题:

ORACLEMYSQLSQL语句简单转换

解决方法:

可以使用一些工具从ORACLE中导出SQL脚本,如使用PLSQLDeveloper中的TOOLS---EXPORT USER OBJECTS。在数据量很小的情况下,也可以以导出INSERT语句的方法导出数据,PLSQLDeveloper中的TOOLS---EXPORT USER OBJECTS中右击选择EXPORT DATA---SQL INSERTS

 

1.关于数据类型:

1)NUMBER---FLOAT

ORACLE:NUMBER(M,N) ,M=1 to 38,N=-84 to 127 可变长的数值列,允许0、正值及负值,M是所有有效数字的位数,N是小数点以后的位数。

 

MYSQL:FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]

单精度浮点数,允许从3.402823466E+38 -1.175494351E-38的值。

M表示总的位数,D表示小数位数。其中M,D可不指定,或只指定M

 

(ORACLE中的NUMBERMYSQL有时候可以直接用INT型替代:

MYSQL:INT(M) 范围从-2147483648 2147483647。无符号整型则是0 4294967295 )

 

 

2)VARCHAR2---VARCHAR

ORACLE:VARCHAR2(M)

变长字符串。M表示最大长度。MYSQL5.0.18NTM0-4000

 

MYSQL:VARCHAR(M) [BINARY]

变长字符串。M表示最大长度。MYSQL5.0.18NTM0-21845

 

 

3)CHAR---CHAR

ORACLE:CHAR(L),定长字符串,L1-2000

MYSQL:CHAR(L),定长字符串,LMYSQL5.0.18NTL0-255

 

 

4)DATE---DATETIME

ORACLE:从公元前471211到公元47121231的所有合法日期,内部是按7个字节来保存日期数据,在定义中还包括小时、分、秒。缺省格式为DD-MON-YY

 

MYSQL:DATETIME

结合日期和时间,支持范围从'1000-01-01 00:00:00' '9999-12-31 23:59:59'.

 

 

2.关于自增列:

ORACLE中自增列用SEQUENCETRIGGER实现。

MYSQL中则使用AUTO_INCREMENT关键字,但是无法指定自增列的起始值。

MYSQL中可以在INSERT语句中向自增列插入需要的值。

 

 

3.关于默认值:

MYSQL(5.0.18NT)中字段的默认值必须为常量,而不能是函数或表达式。

例如,在ORACLE中为DATE类型的字段指定SYSDATE为默认值,在MYSQL中则无法实现。

 

(MYSQL,表中第一个TIMESTAMP类型的字段在插入操作时将插入当前系统时间,但是TIMESTAMP类型的有效范围是1970-2037)

 

 

4.关于系统对象:

DT开头的函数或存储过程通常是数据库系统生成的,如DT_ADDUSEROBJECT

DT_DROPUSEROBJECTBYID等,可略过。

 

 

5.关于存储过程等:

存储过程、视图等语句块中,需要修改的地方如:字符串操作、系统函数的使用等等。

 

 

 

9.遇到的问题:

C#中关于线程的简单编程

解决方法:

示例程序:

class RunThreadSecond

{

    private Thread myThread;

 

    public RunThreadSecond()

    {

        myThread = new Thread(new ThreadStart(ThreadMethod));

        myThread.Name = "MyThread";

        myThread.Start();

    }

 

    private void ThreadMethod()

    {

        while (true)

        {

            try

            {

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

                {

                    Console.WriteLine("My Thread Do Some Work. " + i.ToString());

                }

               

                Thread.Sleep(Timeout.Infinite);

            }

            catch (ThreadInterruptedException)

            {

                Console.WriteLine("My Thread Can't Go Sleep Because Interrupt Method Has Been Called.\n");

            }

        }

    }

 

    public void WakeUpMyThread()

    {

        if (myThread.ThreadState == ThreadState.WaitSleepJoin)

        {

            myThread.Interrupt();

        }

    }

}

 

主线程:

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("Main Thread Running.");

            Console.WriteLine();

 

            RunThreadSecond rts = new RunThreadSecond();

 

            Console.WriteLine("Main Thread Sleep.");

            Console.WriteLine();

            Thread.Sleep(500);

 

            Console.WriteLine("\nWake Up My Thread.");

            Console.WriteLine();

            rts.WakeUpMyThread();

 

            Console.WriteLine("Main Thread Sleep.");

            Console.WriteLine();

            Thread.Sleep(500);

 

            rts.WakeUpMyThread();

            Thread.Sleep(500);

           

            Console.Read();

        }

    }

 

运行结果:

Main Thread Running.

Main Thread Sleep.

 

My Thread Do Some Work.0

My Thread Do Some Work.1

My Thread Do Some Work.2

 

Wake Up My Thread.

Main Thread Sleep.

 

My Thread Can't Go Sleep Because Interrupt Method Has Been Called.

 

My Thread Do Some Work.0

My Thread Do Some Work.1

My Thread Do Some Work.2

 

My Thread Can't Go Sleep Because Interrupt Method Has Been Called.

 

My Thread Do Some Work.0

My Thread Do Some Work.1

My Thread Do Some Work.2

 

由于线程MyThread的任务(即方法ThreadMethod())是永远不会结束的,每次调用myThread.Interrupt();线程就继续剩下的任务,然后被阻塞。注意ThreadInterruptedException出现的时间。

 

Thread.Interrupt()方法:中断处于 WaitSleepJoin 线程状态的线程。该方法将在线程所执行的方法处引起异常,当线程方法试图调用线程的Sleep方法时,线程会由于ThreadInterruptedException而立即被唤醒。

 

ThreadInterruptedException中断处于等待状态的 Thread 时引发的异常。创建线程后,该线程将处于一个或多个 ThreadState 状态中,直到被销毁。当线程处于 WaitSleepJoin 状态时调用 Interrupt 将导致引发 ThreadInterruptedException

 

 

 

0.遇到的问题:

关于跨线程调用WINDOWS控件

解决方法:

.NET2.0的线程编程过程中,有时会遇到"线程间操作无效: 从不是创建控件的线程访问它。"这是由于线程当前所操作的控件并非由本线程创建。

例如,当你写了如下的代码:

private void button1_Click(object sender, EventArgs e)

{

Thread mT = new Thread(new ThreadStart(myThread));           

mT.Start();

}

 

private void myThread()

{

while (true )

{

listBox1.Items.Add(DateTime.Now.ToString());

}

}

 

.NET2.0中须写成:

private delegate void myDel();

 

private void button1_Click(object sender, EventArgs e)

{

Thread mT = new Thread(new ThreadStart(myThread));           

mT.Start();

}

 

private void myThread()

{

while (true)

{

if (this.listBox1.InvokeRequired)

{

Invoke(new myDel(MyMethod));

}

}

}

 

private void MyMethod()

{

listBox1.Items.Add(DateTime.Now.ToString());

}

 

实际上,上述代码表示:如果调用控件的请求为非本窗体线程,则转为用本线程中的实例来实现它。

 

 

posted @ 2006-05-07 10:02  后厂村思维导图馆  阅读(2555)  评论(2编辑  收藏  举报