(7)C#里的线程和流

 

C#支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行。一个C#程序开始于一个单线程,这个单线程是被CLR和操作系统(也称为“主线程”)自动创建的,并具有多线程创建额外的线程。这里的一个简单的例子及其输出:

  调用Start方法后,线程开始运行,线程一直到它所调用的方法返回后结束。

 

命名线程

  线程可以通过它的Name属性进行命名,这非产有利于调试:可以用Console.WriteLine打印出线程的名字,Microsoft Visual Studio可以将线程的名字显示在调试工具栏的位置上。线程的名字可以在被任何时间设置——但只能设置一次,重命名会引发异常。

  程序的主线程也可以被命名,下面例子里主线程通过CurrentThread命名:

没想到看不见的线程可以通过名字来区分,真是太可爱了。。

 

为了强化大家对线程的理解,再附上一个例子:

该示例创建一个名为 Worker 的类,该类包含辅助线程将执行的方法 DoWork。这实际上是辅助线程的 Main 函数。辅助线程将通过调用此方法来开始执行,并在此方法返回时自动终止。既然线程如此强大,为什么不多整几个呢?这里又引出了另一个问题。。。

何时使用多线程

    多线程程序一般被用来在后台执行耗时的任务。主线程保持运行,并且工作线程做它的后台工作。对于Windows Forms程序来说,如果主线程试图执行冗长的操作,键盘和鼠标的操作会变的迟钝,程序也会失去响应。由于这个原因,应该在工作线程中运行一个耗时任务时 添加一个工作线程,即使在主线程上有一个有好的提示“处理中...”,以防止工作无法继续。这就避免了程序出现由操作系统提示的“没有相应”,来诱使用户 强制结束程序的进程而导致错误。模式对话框还允许实现“取消”功能,允许继续接收事件,而实际的任务已被工作线程完成。BackgroundWorker恰好可以辅助完成这一功能。

  何时不要使用多线程

    多线程也同样会带来缺点,最大的问题是它使程序变的过于复杂,拥有多线程本身并不复杂,复杂是的线程的交互作用,这带来了无论是否交互是否是有意的,都会 带来较长的开发周期,以及带来间歇性和非重复性的bugs。因此,要么多线程的交互设计简单一些,要么就根本不使用多线程。除非你有强烈的重写和调试欲 望。当用户频繁地分配和切换线程时,多线程会带来增加资源和CPU的开销。

多线程的应用十分广泛,但是有利有弊,大家编程的时候注意平衡就好。

 

 

下面讲下自己学习“流”的一些心得,在我看来,C#的数据传输都是靠流来实现,数据随着涓涓细流流向他们该去的地方,精确无误,十分高效。特别是文件的传输,万万离不开流。

MemoryStream类用于向内存而不是磁盘读写数据。MemoryStream封装以无符号字节数组形式存储的数据,该数组在创建 MemoryStream对象时被初始化,或者该数组可创建为空数组。可在内存中直接访问这些封装的数据。内存流可降低应用程序中对临时缓冲区和临时文件 的需要。

memoryStream的使用实例:

using System;  
using System.IO;  
using System.Text;  
class program{  
static void Main()  
{  
int count;  
byte[] byteArray;  
char[] charArray;  
UnicodeEncoding uniEncoding=new UnicodeEncoding();  
byte[] firstString=uniEncoding.GetBytes("努力学习");  
byte[] secondString=uniEncoding.GetBytes("不做C#中的菜鸟");  
using (MemoryStream memStream=new MemoryStream(100))  
{  
memStream.Write(firstString,0,firstString.Length);  
count=0;  
while(count<secondString.Length)  
{  
memStream.WriteByte(secondString[count++]);  
}  
Console.WriteLine("Capacity={0},Length={1},Position={2}\n",memStream.Capacity.ToString(),memStream.Length.ToString(),memStream.Position.ToString());  
memStream.Seek(0, SeekOrigin.Begin);  
byteArray=new byte[memStream.Length];  
count=memStream.Read(byteArray,0,20);  
while(count<memStream.Length)  
{  
byteArray[count++]=Convert.ToByte(memStream.ReadByte());  
}  
charArray=new char[uniEncoding.GetCharCount(byteArray,0,count)];  
uniEncoding.GetDecoder().GetChars(byteArray,0,count,charArray,0);  
Console.WriteLine(charArray);  
Console.ReadKey();  
}  
}  
}

关于文件流的写入与读出,这里提供给读者两个代码片段:

文件流写入:

 private void btnChooseOpenFile_Click(object sender, EventArgs e)
        {
            //选择文本框 对象
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.InitialDirectory = @"C:\Users\John\Desktop";
            //如果用户确定
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                //将用户选择的文件路径显示在文本框上
                txtFilePathOpen.Text = ofd.FileName;
            }
        }

        //保存文件
        private void btnSave_Click(object sender, EventArgs e)
        {
            string strContent = txtInputSave.Text.Trim();
            //创建文件流(文件路径,文件操作、创建)
            using (FileStream fs = new FileStream(txtFilePathOpen.Text, FileMode.Create))
            {
                //将字符串字符串转成byte数组
                byte[] byteFile = Encoding.UTF8.GetBytes(strContent);
                //参数:要写到文件的数据数组,从第几个开始写,一共写多少个
                fs.Write(byteFile, 0, byteFile.Length);
                MessageBox.Show("保存成功!");
            }
        }

文件流读出:

private void btnChooseOpenFile2_Click(object sender, EventArgs e)
        {
            //选择文本框 对象
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.InitialDirectory = @"C:\Users\John\Desktop";
            //如果用户确定
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                //将用户选择的文件路径显示在文本框上
                txtFilePathOpen2.Text = ofd.FileName;
            }
        }

        private void btnRead_Click(object sender, EventArgs e)
        {
            using (FileStream fs = new FileStream(txtFilePathOpen2.Text, FileMode.Open))
            {
                byte[] byteData = new byte[1024 * 1024 * 4];
                //返回读取的长度
                int length=fs.Read(byteData,0,byteData.Length);
                if (length > 0)
                {
                    string strData = Encoding.UTF8.GetString(byteData);
                    txtOutputRead.Text = strData;
                    MessageBox.Show("读取成功");
                }
            }
        }

目前我对流的理解止步于此,不过今后我会对这方面多加关注,如果这篇博客有什么不对的地方,还望大家指出,共同学习,一起进步。

posted @ 2015-05-04 21:40  shenyuelong  阅读(603)  评论(0编辑  收藏  举报