日期:2014-05-19  浏览次数:20993 次

线程抢占重复执行的问题
最近开发一个多线程上传的Web系统,通过网页将文件多线程上传到服务器。

下面是主程序部分代码:
fs   =   new   FileStream(filePath,   FileMode.Open,   FileAccess.Read,   FileShare.ReadWrite);
fs.Position   =   0;
UploadThread   thd   =   null;     //文件上传的子线程的对象
ManualResetEvent[]   events   =   new   ManualResetEvent[threadCount];
for   (int   i   =   0;   i   <   threadCount;   i++)
{
events[i]   =   new   ManualResetEvent(false);
realSize   =   ((fileSize   -   i   *   bufferSize)   >   bufferSize)   ?   bufferSize   :   (int)(fileSize   -   i   *   bufferSize);
if   (realSize   <   bufferSize)
{
byte[]   dataOdd   =   new   byte[realSize];
fs.Read(dataOdd,   0,   realSize);
thd   =   new   UploadThread(fileName,   readedSize,   dataOdd);     //文件上传的子线程的实例
readedSize   +=   realSize;
}
else
{
fs.Read(dataTemp,   0,   bufferSize);
thd   =   new   UploadThread(fileName,   readedSize,   dataTemp);
readedSize   +=   bufferSize;
}
ThreadPool.QueueUserWorkItem(new   WaitCallback(thd.UploadFile),   events[i]);     //   将子线程加入线程队列
Thread.Sleep(1000);     //主线程休眠1000毫秒!!!!!!!!!!!!!问题重点!!!!!!!!!!!!!
}
WaitHandle.WaitAll(events);


自线程中写文件方式:
fs   =   new   FileStream(filePath,   FileMode.OpenOrCreate,   FileAccess.Write);
fs.Position   =   startPosition;
fs.Write(ByteData,   0,   size);
fs.Flush();


问题一:
上面标注的“问题重点”处,如果不强制主线程休眠的话,就会出现有些线程抢占其他线程的时间片,重复执行多次,而有些线程根本得不到执行的情况;我想知道本来线程们都已进入排队队列中了为什么还会出现这种情况,除了强制主线程休眠外还有没有其他办法?因为目前这样做上传过程中仍然会丢数据。

问题二:
目前采用FileStream的文件读写方式,位置参数只能是int型,如果大文件的话就会有问题;有没有更好的方式?

------解决方案--------------------
join用在这里的话貌似会失去多线程的意义了吧?
------解决方案--------------------
线程调度一般是发生IO的线程容易被挂起,而最近的线程可能会被最快切换回来,因为这样可能开销最小,
所以没有主thread的sleep,很可能最早创建的线程在fs.write时被晾在一边,直到很后面才恢复,而后创建的线程反倒一直得到运行

其它的一些想法

byte[] dataOdd = new byte[realSize];

建议改成
byte[,] dataOdd;
for 循环之前
dataOdd = new byte[threadCount, bufferSize];

for循环中改
fs.Read(dataOdd[i], 0, realSize);
thd = new UploadThread(fileName, readedSize, dataOdd[i]);

语法上可能有点问题,反正意思是缓冲区分离

另外,msdn上waitall是使用WaitHandle.WaitAll(new WaitHandle[]{mre1, mre2, mre3});
使用WaitHandle数组,不知道有没有关系



------解决方案--------------------
我认为int型表示文件长度足够了,如果比int型表示的最大长度还长的文件,你是无法处理的!