How to ensure that part of code (which contains async) would be called only once?
c#, multithreading, thread-safety, windows-phone-7
Solution
Put in the class:
private int entered = 0;
and in the method:
if (Interlocked.Increment(ref entered) != 1)
{
return;
}
Only the first call to the method will be able to change `entered` from 0 to 1. The others will make it 2, 3, 4, 5...
Clearly you'll need something to reset the `entered` if you want your method to be refireable...
Interlocked.Exchange(ref entered, 0);
at the end of a successful call to the method.
Ah... and it isn't possible to use `lock`/`Monitor.*` around an `await`, because the current thread of the method can change, while nearly all the synchronization libraries expect that the thread you use to enter a lock is the same you use to exit the lock.
You can even use the `Interlocked.CompareExchange()`...
if (Interlocked.CompareExchange(ref entered, 1, 0) != 0)
{
return;
}
The first thread to enter will be able to exchange the value of entered from 0 to 1, and it will receive the old value, 0 (so failing the if and continuing in the remaining code). The other threads will fail the `CompareExchange` and see the "current" value of 1, so entering the if and exiting the method
Problem
So, I have a method, which contains async call to the server. That code is called from 3rd party tool, which somehow sometimes calls same method several times in a row from different threads, so I can't affect that. What I want to be sure is that my method is called once, and then, another calls should be ignored. At first, I tried to lock(locker) with bool isBusy, but that is not satisfied me, as async request was still called several times from second thread, which was fast enough to see isBusy=true; Then, I tried Monitor ``` object obj = new object(); Monitor.TryEnter(obj); try { var res = await _dataService.RequestServerAsync(SelectedIndex, e.StartIndex, e.Count); **** } finally { Monitor.Exit(obj); } ``` However, on `Exit()`, I'm getting exception: A first chance exception of type 'System.Threading.SynchronizationLockException' Is there any other way to guarantee only 1 time execution of the code?