• (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("读取成功");
                    }
                }
            }

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

  • 相关阅读:
    牛客网 二叉树的镜像 JAVA
    牛客网 反转链表 JAVA
    牛客网 调整数组顺序使奇数位于偶数前面 JAVA
    Integer to Roman LeetCode Java
    Valid Number leetcode java
    Longest Common Prefix
    Wildcard Matching leetcode java
    Regular Expression Matching
    Longest Palindromic Substring
    Add Binary LeetCode Java
  • 原文地址:https://www.cnblogs.com/shenyuelong/p/4477620.html
Copyright © 2020-2023  润新知