考多線程讀寫檔案(三種方法)
以下轉貼
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);
}
}