考多线程读写文件(三种方法)
以下转贴
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();
}
}
}
以下转贴
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();
//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);
}
{
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);
}
{
binaryWriter = new BinaryWriter(fileStream);
}
catch (IOException e)
{
fileStream.Close();
throw new IOException("构造BinaryWriter对象时出错", e);
}
try
{
//将该流的当前位置设置为适当的位置
fileStream.Seek(0, SeekOrigin.End);//此方法可能出现出现 I/O 错误,抛出IOException异常
{
//将该流的当前位置设置为适当的位置
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();
}
}
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);
}
}