SynchronizationLockException on Monitor.Exit when using await

前端 未结 3 393
逝去的感伤
逝去的感伤 2020-11-29 11:24

I am creating a piece of code that gets a webpage from a legacy system we have. In order to avoid excessive querying, I am caching the obtained URL. I am using Monitor

3条回答
  •  隐瞒了意图╮
    2020-11-29 11:56

    In SendRequest however, I need to 'await', and thus I'm unable to use lock for some reason I didn't give much thought, so the solution to synchronize is to use Monitor.

    Should have given it more thought. :)

    There are two problems with using blocking locks with async code.

    The first problem is that - in the general case - an async method may resume executing on a different thread. Most blocking locks are thread-affine, meaning that they must be released from the thread that owns them (the same thread that acquired the lock). It is this violation of Monitor thread-affinity that causes the SynchronizationLockException. This problem does not happen if the await captures an execution context (e.g., a UI context) and used that to resume the async method (e.g., on the UI thread). Or if you just got lucky and the async method happened to resume on the same thread pool thread.

    However, even if you avoid the first problem, you still have a second problem: any arbitrary code can execute while an async method is "paused" at an await point. This is a violation of a cardinal rule of locking ("do not execute arbitrary code while holding a lock"). For example, thread-affine locks (including Monitor) are generally re-entrant, so even in the UI thread scenario, when your async method is "paused" (and holding the lock), other methods running on the UI thread can take the lock without any problems.

    On Windows Phone 8, use SemaphoreSlim instead. This is a type that allows both blocking and asynchronous coordination. Use Wait for a blocking lock and WaitAsync for an asynchronous lock.

提交回复
热议问题