现在在作C#小项目(winform),遇到一个多线程的问题,我的想法是:读一个文件,得到一个流,然后用多个线程把这个流保存为文件名不同的文件(在其他目录),就像复制一样。所以专门写了一个类worker,里面有用于把读到的流按照文件名保存为文件的一个方法,所以我构造了多个线程,同时访问这个类的这个方法,但每次访问文件名参数不同,我想如果这个方法是Static的,能不能让多线程同时访问(一定要并发)?(我试了,但老有问题,why??)要不想保存几个文件就要实例化几个worker类,然后各个线程再访问不同的worker实例的方法,但这样还是有问题,第2个文件保存不上!!把代码帖出来,给大家看看,帮我找一下错误,把代码中的文件名改一下就能运行了
using System;
using System.IO;
using System.Threading;
using System.Text;
class worker
{
public Stream s=null;
public string sf=null;
public void save()
{//Monitor.Enter(this);
bool ifok=testSave(this.s,this.sf);
Console.WriteLine("Thread{0}进入!!!"+Thread.CurrentThread.GetHashCode());
if(ifok)
Console.WriteLine("保存文件成功");
else
Console.WriteLine("保存文件失败");
//Monitor.Exit(this);
}
public bool testSave(Stream s,string saveFile)//就是把这个方法搞成static的行不??
{
try
{
FileStream FileWriteStream=new FileStream (saveFile,FileMode.Create,FileAccess.Write);
BufferedStream bufferedStreamW=new BufferedStream(FileWriteStream);
BufferedStream bufferedStreamR=new BufferedStream(s);
byte[] byteBuffer=new byte[256];
int intByte=0;
do{
intByte=bufferedStreamR.Read(byteBuffer,0,256);
bufferedStreamW.Write(byteBuffer,0,intByte);
bufferedStreamR.Flush();
bufferedStreamW.Flush();
}while(intByte>0);
bufferedStreamW.Close();
bufferedStreamR.Close();
}
catch(Exception e)
{Console.WriteLine("---"+e.Message+"----");
return false;
}
return true;
}
}
class main
{
static worker work1=null;
static worker work2=null;
public static void Main()
{
main ma=new main();
FileStream fs=new FileStream("c:\\Test.Html",FileMode.Open,FileAccess.Read);
Console.WriteLine("-------------------------------------------------------------");
work1=new worker();
work2=new worker();
Stream s=fs;
Thread t1=ma.CreateThread(work1,fs,"C:\\1.txt");
t1.Start();
Thread t2=ma.CreateThread(work2,fs,"C:\\2.txt");//如果这里参数work1,work2一样行不?
//就是线程同时访问一个对象的一个方法
//我试的这样只能有一个文件被存上?
t2.Start();
Console.ReadLine();
}
private Thread CreateThread(worker work,Stream s,string sf)
{
work.s=s;
work.sf=sf;
Thread t=new Thread(new ThreadStart(work.save));
return t;
}
}
using System;
using System.IO;
using System.Threading;
using System.Text;
class worker
{
public Stream s=null;
public string sf=null;
public void save()
{//Monitor.Enter(this);
bool ifok=testSave(this.s,this.sf);
Console.WriteLine("Thread{0}进入!!!"+Thread.CurrentThread.GetHashCode());
if(ifok)
Console.WriteLine("保存文件成功");
else
Console.WriteLine("保存文件失败");
//Monitor.Exit(this);
}
public bool testSave(Stream s,string saveFile)//就是把这个方法搞成static的行不??
{
try
{
FileStream FileWriteStream=new FileStream (saveFile,FileMode.Create,FileAccess.Write);
BufferedStream bufferedStreamW=new BufferedStream(FileWriteStream);
BufferedStream bufferedStreamR=new BufferedStream(s);
byte[] byteBuffer=new byte[256];
int intByte=0;
do{
intByte=bufferedStreamR.Read(byteBuffer,0,256);
bufferedStreamW.Write(byteBuffer,0,intByte);
bufferedStreamR.Flush();
bufferedStreamW.Flush();
}while(intByte>0);
bufferedStreamW.Close();
bufferedStreamR.Close();
}
catch(Exception e)
{Console.WriteLine("---"+e.Message+"----");
return false;
}
return true;
}
}
class main
{
static worker work1=null;
static worker work2=null;
public static void Main()
{
main ma=new main();
FileStream fs=new FileStream("c:\\Test.Html",FileMode.Open,FileAccess.Read);
Console.WriteLine("-------------------------------------------------------------");
work1=new worker();
work2=new worker();
Stream s=fs;
Thread t1=ma.CreateThread(work1,fs,"C:\\1.txt");
t1.Start();
Thread t2=ma.CreateThread(work2,fs,"C:\\2.txt");//如果这里参数work1,work2一样行不?
//就是线程同时访问一个对象的一个方法
//我试的这样只能有一个文件被存上?
t2.Start();
Console.ReadLine();
}
private Thread CreateThread(worker work,Stream s,string sf)
{
work.s=s;
work.sf=sf;
Thread t=new Thread(new ThreadStart(work.save));
return t;
}
}
这里的fs里面会维护一个当前位置的变量。 如果多个线程并发访问它的话该变量肯定
会乱。
修改建议:如果文件比较小,就一次将之读入到内存缓冲中,然后每个线程都直接将
将这个内存缓冲写入文件。
如果文件比较大,那么在fs的读操作上加上互斥锁,然后在每个线程中维护一个
文件当前位置的变量,每次都以绝对位置读文件。
再说一句:你碰到的问题最直接的原因应该是第一个线程读完文件后没有将文件
位置指针重置。
{ public Stream s=null;
lock(s)
{
public string sf=null;
public void save()
{//Monitor.Enter(this);
bool ifok=testSave(this.s,this.sf);
Console.WriteLine("Thread{0}进入!!!"+Thread.CurrentThread.GetHashCode());
if(ifok)
Console.WriteLine("保存文件成功");
else
Console.WriteLine("保存文件失败");
//Monitor.Exit(this);
}
}
补上的,试试管用吗,应该可以的,因为多线程中您写的:
work1=new worker();
work2=new worker();
Stream s=fs;
Thread t1=ma.CreateThread(work1,fs,"C:\\1.txt");
t1.Start();
Thread t2=ma.CreateThread(work2,fs,"C:\\2.txt");//如果这里参数work1,work2一样行不?
使对象 s 调用的顺序与实际的不同。