zoukankan      html  css  js  c++  java
  • (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("读取成功");
                    }
                }
            }

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

  • 相关阅读:
    svn自动部署
    【阿里云】Windows2008 FTP配置指南
    thinkphp 3.2多语言设置
    iphone、ipod Touch、ipad触屏时的js事件
    Nginx区分PC或手机访问不同网站
    Nginx Location配置总结及基础最佳实践
    阿里云官方教程 Linux 系统挂载数据盘
    利用php调用so库文件中的代码
    LINUX下PHP编译添加相应的动态扩展模块so(不需要重新编译PHP,以openssl.so为例)
    Android深入理解Context(三)Context完全解析
  • 原文地址:https://www.cnblogs.com/shenyuelong/p/4477620.html
Copyright © 2011-2022 走看看