1

我有一个应用程序,它在 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);
    }
}
4

1 回答 1

0

谢谢你的建议 usr。事实证明是文件流写入导致了问题。

事实证明,当您使用 FileStream.SetLength() 为大文件分配文件空间然后寻找该文件深处的部分时,一旦您开始在文件中的该位置写入,稀疏文件空间将被“回填”这可能很慢。我在代码中的锁只是通过让未阻塞的段等待繁忙的段来暴露问题。

我将发布一个单独的问题,看看是否有更有效的方法来编写/创建这些文件。

于 2013-07-23T17:13:11.320 回答