weixin_39589253
2020-12-31 01:55 阅读 5

MultiThreadDownloader类抛出System.IO.IOException

在此前的issue中已有相同问题,但我发现改问题仍未得到妥善的解决。

我不确定是否是我的代码问题引起异常,因此我创建了一个测试工程以复现问题 环境:.Net Framework 4.6.1 Nuget版本:Masuit.Tools.Net 2.2.8.9 代码如下:


static void Main(string[] args)
        {
            var mtd1 = new MultiThreadDownloader("url",  Environment.CurrentDirectory+"\\test1.png", 1);
            mtd1.Start();
            Console.ReadLine();

            var mtd2 = new MultiThreadDownloader("url", Environment.CurrentDirectory + "\\test2.png", 1);
            mtd2.Start();
            Console.ReadLine();
        }

以下是异常信息: System.IO.IOException HResult=0x80070020 Message=文件“C:\Users\23877\AppData\Local\Temp\c5ef965e-b056-4a54-9090-6af3b596eefc”正由另一进程使用,因此该进程无法访问此文件。 Source=mscorlib StackTrace: 在 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) 在 System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost) 在 System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access) 在 Masuit.Tools.Net.MultiThreadDownloader.MergeParts() 在 Masuit.Tools.Net.MultiThreadDownloader.temp_DownloadPartCompleted(Object sender, EventArgs e) 在 Masuit.Tools.Net.PartialDownloader.b__60_0(Object state) 在 System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state) 在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 在 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 在 System.Threading.ThreadPoolWorkQueue.Dispatch() 在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

该提问来源于开源项目:ldqk/Masuit.Tools

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

4条回答 默认 最新

  • weixin_39902345 weixin_39902345 2020-12-31 01:55

    这个问题经测试了没法复现,能否提供下更详细的调用方式,以供debug?

    点赞 评论 复制链接分享
  • weixin_39589253 weixin_39589253 2020-12-31 01:55

    该问题已解决。 在PartialDownloader.cs的DownloadProcedure方法里面,把using var file...改成using(file=...){...}问题就解决了。 `void DownloadProcedure(Action config) { using(var file = new FileStream(FullPath, FileMode.Create, FileAccess.ReadWrite)) { var sw = new Stopwatch(); if (WebRequest.Create(Url) is HttpWebRequest req) { req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36"; req.AllowAutoRedirect = true; req.MaximumAutomaticRedirections = 5; req.ServicePoint.ConnectionLimit += 1; req.ServicePoint.Expect100Continue = true; req.ProtocolVersion = HttpVersion.Version11; config(req); ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3; ServicePointManager.Expect100Continue = true; if (RangeAllowed) { req.AddRange(From, _to); }

                    if (req.GetResponse() is HttpWebResponse resp)
                    {
                        ContentLength = resp.ContentLength;
                        if (ContentLength <= 0 || (RangeAllowed && ContentLength != _to - From + 1))
                        {
                            throw new Exception("Invalid response content");
                        }
    
                        using var tempStream = resp.GetResponseStream();
                        int bytesRead;
                        byte[] buffer = new byte[4096];
                        sw.Start();
                        while ((bytesRead = tempStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            if (_totalBytesRead + bytesRead > ContentLength)
                            {
                                bytesRead = (int)(ContentLength - _totalBytesRead);
                            }
    
                            file.Write(buffer, 0, bytesRead);
                            file.Flush();
                            _totalBytesRead += bytesRead;
                            _lastSpeeds[_counter] = (int)(_totalBytesRead / Math.Ceiling(sw.Elapsed.TotalSeconds));
                            _counter = (_counter >= 9) ? 0 : _counter + 1;
                            int tempProgress = (int)(_totalBytesRead * 100 / ContentLength);
                            if (Progress != tempProgress)
                            {
                                Progress = tempProgress;
                                _aop.Post(state =>
                                {
                                    DownloadPartProgressChanged?.Invoke(this, EventArgs.Empty);
                                }, null);
                            }
    
                            if (Stopped || (RangeAllowed && _totalBytesRead == ContentLength))
                            {
                                break;
                            }
                        }
                    }
    
                    req.Abort();
                }
                sw.Stop();
            }
    
    
            if (!Stopped && DownloadPartCompleted != null)
            {
                _aop.Post(state =>
                {
                    Completed = true;
                    DownloadPartCompleted(this, EventArgs.Empty);
                }, null);
            }
    
            if (Stopped && DownloadPartStopped != null)
            {
                _aop.Post(state => DownloadPartStopped(this, EventArgs.Empty), null);
            }
        }`
    
    点赞 评论 复制链接分享
  • weixin_39902345 weixin_39902345 2020-12-31 01:55

    按道理using var file...和using(file=...){...}应该是一个意思的,只是语法糖而已啊🤔🤔

    点赞 评论 复制链接分享
  • weixin_39876514 weixin_39876514 2020-12-31 01:55

    代码没有贴全,推测:2种方式作用域不一样,他这里代码比较多,可能影响到了。 而包裹起来是自己控制作用域的

    点赞 评论 复制链接分享

相关推荐