我有一个应用程序,可以在4个不同的段中下载单个文件(每个段是一个不同的长时间运行的任务),并定期序列化进度。
当序列化在2核心机器上进行时,该过程将阻塞3-10秒然后完成。一旦这种阻塞行为发生在第一次它永远不会再发生。第2个(n)调用序列化立即执行顺利执行。似乎在第一次调用阻塞期间,框架执行了一些任务/线程优化,以防止再次发生阻塞行为。
是否有人对此优化有任何了解,是否可以在初始化时执行此类优化以避免阻塞行为?
以下是一些有助于描述情况的伪代码:
class Download
{
private DownloadSegment[] _downloadSegments = new DownloadSegment[4];
public void StartDownload()
{
for (int i = 0; i < 4; i++)
{
_downloadSegments[i] = new DownloadSegment();
_downloadSegments[i].Start();
}
}
public void Serialize()
{
try
{
//enter lock so the code does not serilize the progress while
//writing new downloaded info at the same time
foreach(DownloadSegment segment in _downloadSegments)
{
Monitor.Enter(segment.SyncRoot);
}
//code to serialize the progress
}
finally
{
foreach (DownloadSegment segment in _downloadSegments)
{
Monitor.Exit(segment.SyncRoot);
}
}
}
}
class DownloadSegment
{
public object SyncRoot = new object();
public void Start()
{
Task downloadTask = new Task(
() =>
{
//download code
lock (SyncRoot)
{
//wirte to disk code
}
},
new CancellationToken(),
TaskCreationOptions.LongRunning);
downloadTask.Start(TaskScheduler.Default);
}
}
答案 0 :(得分:0)
感谢您的建议。事实证明是文件流写入导致问题。
事实证明,当您使用FileStream.SetLength()为大文件分配文件空间然后寻找该文件内部的一个部分时,一旦您开始在文件中的该位置写入,稀疏文件空间将是“回填”,这可能很慢。我在代码中使用的锁只是通过使未阻塞的段等待繁忙的段来公开问题。
我将发布一个单独的问题,看看是否有更有效的方法来编写/创建这些文件。