I got the following code snippet:

public Task DistributeAsync(BankAccount account, decimal amount)
{
    lock (account)
    {
        return repository.AddLoanAsync(account, amount).ContinueWith(task => 
        {
            if (!task.Result)
            {
                throw new LoanException();
            }
        }
    }
}

// Somewhere else in the code:
var distributeTask = distributor.DistributeAsync(bankAccount, 42000);

And I am wondering how I can rewrite this properly using async/await keywords for more readability. I am currently facing the issue that I am not allowed to use await within the body of a lock statement. Any help to get me in the right direction would be appreciated.

I am aware of the lock statement not being thread safe, this snippet is part of a bigger exercise and another question is to explain why that lock does not help making the code thread safe!

  • 1
    would the async semaphore slim help? – Ewan Dec 1 at 12:49
  • can you add the calling code in such a way that it demonstrates what you are trying to prevent with the lock? – Ewan Dec 1 at 12:51
  • @Ewan I am not allowed to use those semaphores. It's just async / await keywords I am allowed to use. I have discussed this question with my peers, and the gist of it comes down to: move the lock to the AddLoanAsync method within the repository, then you can make the method async and the return type awaitable. This is all the code I have unfortunately, it's very vague and we already suggested that this might be a trick question, i.e. it is not possible to add async/await without modifying some code (see above). – J. Doe Dec 1 at 13:11
  • 1
    what i mean is, why not just remove the lock? why have the function at all when it just calls another function? there must be a dozen 'solutions' – Ewan Dec 1 at 13:18
  • it seems to me like you are missing some sort of validation, account.balance > 0 or similar and then a later action which would require the lock to prevent the balance changing in between the statements. – Ewan Dec 1 at 13:34

Use await instead of returning Task and ContinueWith then use SemaphoreSlim for locking. Your code without locking should look something like this.

if (!(await repository.AddLoanAsync(account, amount)))
{
   throw new LoanException();
}

Your should call it like this

await distributor.DistributeAsync(bankAccount, 42000);

You should only use return instead of using await when only thing that method does is returning another task.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.