5

我有一些从 SO 帖子和其他网站收集的 Web API 代码。但是,任务的东西对我来说仍然是新的。我正在尝试将上传的文件复制到新位置,但有时(并非总是)我在尝试复制文件时遇到异常。异常表明该文件正在被另一个进程使用。不过,它并非每次都会发生。我想我需要将复制操作移到其他地方。这是我的代码。有什么建议么?

var provider = new MultipartFormDataStreamProvider(uploadroot);
                var task = Request.Content.ReadAsMultipartAsync(provider).ContinueWith<HttpResponseMessage>(t =>
                {
                    if (t.IsFaulted || t.IsCanceled)
                        throw new HttpResponseException(HttpStatusCode.InternalServerError);

                    var docConversionId = Guid.NewGuid().ToString("N");
                    var sourceFilePath = Path.Combine(uploadroot, provider.FileData.First().LocalFileName);
                    var destinationFilePath = Path.Combine(inboxroot, docConversionId);

                    File.Copy(sourceFilePath, destinationFilePath);

                    var response = new HttpResponseMessage(HttpStatusCode.OK);
                    response.Content = new StringContent(docConversionId);
                    //response.Content.Headers.Add("DocumentConversionId", docConversionId);
                    return response;
                });
                return task;
4

3 回答 3

7

在使用 ReadAsMultipartAsync 后立即尝试读取/删除文件可能会遇到一个已知问题。

以下是与之相关的错误(您可以查看解决信息以获取有关其发生原因以及解决方法的更多详细信息):

https://aspnetwebstack.codeplex.com/workitem/176

于 2013-07-19T21:12:45.140 回答
1

由于 codeplex 中的原始讨论已死,我将在 2013 年最初关闭该问题时将原始解释和解决方法粘贴在这里:

我们正在关闭这个问题,因为发现根本原因是在框架代码中。已针对外部合作伙伴团队打开了一个单独的错误,并将在那里跟踪此问题。

变更集: http://aspnetwebstack.codeplex.com/SourceControl/changeset/changes/452b8e1dfa40

恢复我们使用 FileOptions.WriteThrough 的尝试修复,以确保它不是文件缓存和 FileStream 代码之间的竞争。但是 WriteThrough 没有解决核心错误并导致性能下降。

对用户代码的影响是这样的:如果您使用 MultipartFormDataContent 上传文件并使用 MultiPartDataStreamProvider 在服务器上读取它,则在 ReadAsMultipartAsync 完成后服务器上的底层文件可能不会完全关闭。有一个小窗口,本机代码可能仍在另一个线程上释放文件资源。

影响是在异步读取后立即对该文件执行 File.Delete 或 File.OpenRead 可能会失败并出现 IOException(“文件正在被另一个进程使用”)。我们观察到在高负载情况下的故障率约为 0.3%。唯一已知的解决方法是对这些操作进行尝试/捕获,如果发生 IOException,则延迟一小段时间,然后重试。50 毫秒的延迟通常有效,但建议允许多次重试。这允许本机线程完成释放其资源。在我们的压力实验室中,这种捕获延迟重试算法总是成功的。

于 2019-11-19T16:13:54.690 回答
0

我遇到了这个疯狂的问题,发现它适用于await关键字。

await Request.Content.ReadAsMultipartAsync(streamProvider);

无需将任务保存在变量中。

于 2019-03-04T02:52:37.460 回答