【发布时间】:2014-02-19 15:59:02
【问题描述】:
我正在创建一段代码,用于从我们拥有的旧系统中获取网页。为了避免过度查询,我将获取到的 URL 缓存起来。我正在使用Monitor.Enter、Monitor.Exit 并仔细检查以避免发出两次请求,但是当使用Monitor.Exit 释放锁时,我得到了这个异常:
System.Threading.SynchronizationLockException was caught
HResult=-2146233064
Message=Object synchronization method was called from an unsynchronized block of code.
Source=MyApp
StackTrace:
at MyApp.Data.ExProvider.<OpenFeature>d__0.MoveNext() in c:\Users\me\Documents\Visual Studio 2013\Projects\MyApp\MyApp\Data\ExProvider.cs:line 56
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at MyApp.Data.ExProvider.<GetSupportFor>d__15.MoveNext() in c:\Users\me\Documents\Visual Studio 2013\Projects\MyApp\MyApp\Data\ExProvider.cs:line 71
InnerException:
第 56 行是Monitor.Exit。这是执行操作的代码:
private async Task<Stream> OpenReport(String report)
{
var file = _directory.GetFiles(report+ ".html");
if (file != null && file.Any())
return file[0].OpenRead();
else
{
try
{
Monitor.Enter(_locker);
FileInfo newFile = new FileInfo(Path.Combine(_directory.FullName, report + ".html"));
if (!newFile.Exists) // Double check
{
using (var target = newFile.OpenWrite())
{
WebRequest request = WebRequest.Create(BuildUrl(report));
var response = await request.GetResponseAsync();
using (var source = response.GetResponseStream())
source.CopyTo(target);
}
}
return newFile.OpenRead();
}
finally
{
Monitor.Exit(_locker);
}
}
}
那么await 和Monitor 有什么问题?是不是因为Monitor.Enter和Monitor.Exit不是同一个线程?
【问题讨论】:
标签: c# multithreading synchronization task-parallel-library async-await