Basically, I want to make multiple asynchronous requests to a tcp Server. I currently have a working client that is only synchronous and blocks the UI on every network call. Since multiple requests might occur at almost the same time, I tried to do this:
private object readonly readLock = new object(); public async Task UpdateDetailsAsync() { //I want every request to wait their turn before requesting (using the connection) //to prevent a read call from catching any data from another request lock (readLock) { Details details = await connection.GetDetailsAsync(); detailsListBox.Items = details; } }
I am sure this is not a good use of lock but it's the only way I can think of that could make the calls wait for their turn. Is there an object I can use to achieve this kind of behavior? I thought Monitor would be the same so I didn't try (I understand they're multithreading stuff but that's all I'm familiar with...)
Using a plain lock won't work because you can't await inside of a lock. I decided to try a SemaphoreSlim as that has a async method.
The await keyword in C# (. NET Async CTP) is not allowed from within a lock statement. From MSDN: An await expression cannot be used in a synchronous function, in a query expression, in the catch or finally block of an exception handling statement, in the block of a lock statement, or in an unsafe context.
Another solution is to call “ConfigureAwait(false)” on the task of the underlying method, to prevent the continuation of the task on the original context captured. If you really cannot use async all the way, then you could use “Task. Run(…)” to execute the async method in a separate thread.
C# Lock keyword ensures that one thread is executing a piece of code at one time. The lock keyword ensures that one thread does not enter a critical section of code while another thread is in that critical section. Lock is a keyword shortcut for acquiring a lock for the piece of code for only one thread.
Looks like the problem that you have is that threads will block while acquiring the lock, so your method is not completely async. To solve this you can use SemaphoreSlim.WaitAsync
private readonly SemaphoreSlim readLock = new SemaphoreSlim(1, 1); public async Task UpdateDetailsAsync() { //I want every request to wait their turn before requesting (using the connection) //to prevent a read call from catching any data from another request await readLock.WaitAsync(); try { Details details = await connection.GetDetailsAsync(); detailsListBox.Items = details; } finally { readLock.Release(); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With