天天看點

對同一檔案進行多線程寫入

 考多線程讀寫檔案(三種方法)

以下轉貼

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);

        }

}