天天看点

对同一文件进行多线程写入

 考多线程读写文件(三种方法)

以下转贴

using   System;  

  using   System.Threading;  

  using   System.IO;  

  namespace   CopyTest  

  {  

  //FileBuffer用来存放和取出缓冲区变量  

  public   class   FileBuffer{  

  private   int   m_readsize   =   1024;  

  //定义了m_capacity个字节的缓冲区  

  private   byte[]   m_buffer   =   new   byte[4096];  

  //确认缓冲区内已放字节的个数  

  private   int   bufferCount=0;  

  //确定读写的位置  

  private   int   readLocation=0,writeLocation=0;  

  public   FileBuffer()   {  

  }  

  //从缓冲区中取数据  

  public   byte[]   getBuffer()   {  

  //加上了共享锁  

  lock(this)   {  

  //判断如果缓冲区内无内容,则读取者进入wait状态,并且释放对象锁  

  if(bufferCount==0)   {  

  Console.WriteLine("缓冲区无数据,无法读取");  

  Monitor.Wait(this);  

  }  

  byte[]   newBuf   =   new   byte[m_readsize];  

  Buffer.BlockCopy(m_buffer,   readLocation,   newBuf,   0,   m_readsize);  

  //已经从缓冲区读取了内容,所以bufferCount要进行自减.  

  bufferCount-=m_readsize;  

  //求余的目的是为了循环使用缓冲区  

  readLocation=(readLocation   +   m_readsize)%m_buffer.Length;  

  //通知对象的第一个等待线程可以从WaitSleepJoin转换到Started状态.  

  Monitor.Pulse(this);  

  //返回给读取者取出的数值  

  return   newBuf;  

  }  

  }  

  //将数据放入缓冲区  

  public   void   setBuffer(byte[]   writeValue)   {  

  //锁住共享数据区  

  lock(this)   {  

  //如果缓冲区已满,那么进入waitsleepjoin状态  

  if(bufferCount==m_buffer.Length)   {  

  Console.WriteLine("缓冲区溢出!");  

  Monitor.Wait(this);  

  }  

  //向缓冲区写入数据  

  Buffer.BlockCopy(writeValue,   0,   m_buffer,   writeLocation,   m_readsize);  

  //自加,代表缓冲区现在到底有几个数据  

  bufferCount+=m_readsize;  

  //用%实现缓冲区的循环利用  

  writeLocation=(writeLocation   +   m_readsize)%m_buffer.Length;  

  //唤醒waitSleepJoin状态的进程,到started状态  

  Monitor.Pulse(this);  

  }//使用lock隐式的释放了共享锁  

  }  

  }  

  //写入者类,向缓冲区中放入数据  

  public   class   Writer   {    

  //定义了同步变量  

  FileBuffer   shared;  

  FileStream   file;  

  //此处构造函数的作用是在启动类中调用写入者的时候,把启动类中定义的sharedLocation传过来  

  public   Writer(FileBuffer   sharedLocation)   {  

  file   =   new   FileStream("C://Test.txt",FileMode.Open);  

  shared=sharedLocation;  

  }  

  //定义写入过程  

  public   void   Write()   {  

  //将数据放入缓冲区  

  Byte[]   datas   =   new   byte[1024];  

  for(int   byteread=0;byteread<=file.Length;byteread   +=   datas.Length)   {  

  file.Read(datas,   byteread,   datas.Length);  

  shared.setBuffer(datas);  

  }  

  file.Close();  

  //得到当前线程的名字  

  string   name=Thread.CurrentThread.Name;  

  //此线程执行完毕  

  Console.WriteLine(name+"done   writeing");  

  }  

  }  

  public   class   Reader   {//定义读取者  

  byte[]   value;  

  FileStream   file;  

  //定义同步变量  

  FileBuffer   shared;  

  //定义构造函数,负责传递启动类中的shared  

  public   Reader(FileBuffer   sharedLocation)   {  

  file   =   new   FileStream("C://Data.txt",FileMode.Create);  

  shared=sharedLocation;  

  }  

  public   void   Read()   {  

  //从缓冲区中循环读取  

  for(int   bytewrite=0;bytewrite<=65535;)   {  

  value=shared.getBuffer();  

  file.Write(value,   bytewrite,   value.Length);  

  bytewrite+=value.Length;  

  }  

  file.Close();  

  //取得当前线程的名字  

  string   name=Thread.CurrentThread.Name;  

  Console.WriteLine(name+"done   reading");  

  }  

  }  

  public   class   ThreadTest   {   //设置为启动类  

  public   static   void   Main()   {  

  FileBuffer   shared=new   FileBuffer();  

  //初始化了写入者和读取者,并且把shared参数传递了过去  

  Writer   Writer1=new   Writer(shared);  

  Reader   Reader1=new   Reader(shared);  

  Thread   WriterThread   =   new   Thread(new   ThreadStart   (Writer1.Write));  

  WriterThread.Name="写入者";  

  Thread   ReaderThread   =   new   Thread(new   ThreadStart   (Reader1.Read));  

  ReaderThread.Name="读取者";  

  //启动这两个线程  

  WriterThread.Start();  

  ReaderThread.Start();  

  WriterThread.Join();  

  ReaderThread.Join();  

  Console.ReadLine();  

  }  

  }  

  }

==========================================================================================

使用Mutex

每个程序在打开文件,进行写的时候,用mutex包含,例如:

Mutex mtx = new Mutex(); mtx.WaitOne();

//Write file here

mtx.ReleaseMutex(); ========================================================================================= private static  void WriteFile(object parm)

        {

            FileStream fileStream = null;

            BinaryWriter binaryWriter = null;

            FileInfo fileInfo = new FileInfo("C://test.txt");

            try

            {

                fileStream = fileInfo.Open(FileMode.Open, FileAccess.Write, FileShare.Write);//注意Open方法的参数

            }

            catch (IOException e)

            {

                throw new IOException("构造FileStream对象时出错", e);

            }             try

            {

                binaryWriter = new BinaryWriter(fileStream);

            }

            catch (IOException e)

            {

                fileStream.Close();

                throw new IOException("构造BinaryWriter对象时出错", e);

            }             try

            {

                //将该流的当前位置设置为适当的位置

                fileStream.Seek(0, SeekOrigin.End);//此方法可能出现出现 I/O 错误,抛出IOException异常                 //将数据块写入文件

                binaryWriter.Write(parm.ToString());//此方法可能出现出现 I/O 错误,抛出IOException异常

            }

            catch (IOException e)

            {

                throw new IOException("将数据块写入文件时出错", e);

            }

            finally

            {

                //关闭流,BinaryWriter也将关闭FileStream对象,所以无需再调用fileStream.Close()

                binaryWriter.Close();

            }

        }

public static void Main()

{

    //多线程写文件

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

        {

                string str= "This is string " + i + " ";

                System.Threading.Thread thread = new System.Threading.Thread(

                    new System.Threading.ParameterizedThreadStart(WriteFile));

                thread.Start(str);

        }

}