我正在创建一段代码,该代码可以从我们拥有的旧系统中获取网页。为了避免过多的查询,我正在缓存获取的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
时线程不同? 最佳答案
您不能在await
范围(这是lock
和Monitor.Enter
的语法糖)内对任务进行Monitor.Exit
。直接使用Monitor
将愚弄编译器,但不会愚弄框架。async-await
不像Monitor
那样具有线程亲和性。 await
之后的代码可能会在与其之前的代码不同的线程中运行。这意味着释放Monitor
的线程不一定是获得它的线程。
在这种情况下,要么不使用async-await
,要么使用其他可以自己构建的同步结构,例如SemaphoreSlim
或AsyncLock
。这是我的:https://stackoverflow.com/a/21011273/885318
关于c# - 使用await时Monitor.Exit上的SynchronizationLockException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21404144/