Forum Cross Platform with Xamarin

Mutex is bugged in Xamarin

Has anyone tried to create a mutex, then WaitOne() before a HttpClient request and release it afterwards? You will get a Mutex is not owned exception... and if you release it just before the PostAsync() methood of the HttpClient class it works... so can you please fix this error?

I'll post my code so you can see what I'm talking about:

public async Task PostDataAsync(string command, Dictionary<string, object> postData)
{
try
{
++ThrottleCounter;
ThrottleSemaphore.WaitOne();

            nonceMutex.WaitOne();
            postData.Add("command", command);
            postData.Add("nonce", Helper.GetCurrentHttpPostNonce());
            var jsonString = await PostStringAsync(Helper.ApiUrlHttpsRelativeTrading, postData);

...
}

private async Task PostStringAsync(string relativeUrl, Dictionary<string, object> postData)
{
using (var client = new HttpClient())
{
var postBytes = Encoding.GetBytes(postData.ToHttpPostString());

                client.DefaultRequestHeaders.Add("Key", Authenticator.PublicKey);
                client.DefaultRequestHeaders.Add("Sign", Encryptor.ComputeHash(postBytes).ToStringHex());
                client.DefaultRequestHeaders.UserAgent.TryParseAdd("CryptoCurr/1.0");

                var pairs = new List<KeyValuePair<string, string>>();
                foreach (var item in postData)
                {
                    pairs.Add(new KeyValuePair<string, string>(item.Key, item.Value.ToString()));
                }
                var content = new FormUrlEncodedContent(pairs);

                nonceMutex.ReleaseMutex();
                var responseMessage = await client.PostAsync(new Uri(BaseUrl + relativeUrl), content);
                string resultContent = await responseMessage.Content.ReadAsStringAsync();

                responseMessage.EnsureSuccessStatusCode();

                return resultContent;
            }

}

if nonceMutex.ReleaseMutex(); is after the var responseMessage = await client.PostAsync(new Uri(BaseUrl + relativeUrl), content); line it throws an Exception Mutex is not owned.

Which is really a pain in the a** because the code the way it is some requests fail because a nonce arrives before another request.

I've tried moving the nonceMutex.ReleaseMutex(); to the other methood right after var jsonString = await PostStringAsync(Helper.ApiUrlHttpsRelativeTrading, postData); and still I get the exception.

Answers

  • Henrique.7684Henrique.7684 USMember ✭✭

    anyone know how can I make this work?

  • GarethBrown.8923GarethBrown.8923 GBMember
    edited February 2018

    I had the same problem. I replaced the mutex with a ManualResetEvent with an initial state to be signalled.

    static readonly ManualResetEvent MyResetEvent = new ManualResetEvent(true);
    
    try 
    {
        MyResetEvent.WaitOne();
        // do something
    }
    finally
    {
        MyResetEvent.Set();
    }
    
  • Kayla_KKayla_K Member

    The issue is likely to be caused by mixing asynchronous and thread blocking coding techniques. In general use one or the other throughout the calling tree. To synchronize access to a shared resource within async methods the SemaphoreSlim class is recommended. Use one of the WaitAsync overloads to wait asynchronously before entering the protected code. E.g.

    private static readonly SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);

    try
    {
        if (await semaphore.WaitAsync(timeout))
        {
            //Execute code protected by the semaphore
        }
        else
        {
            //Handle semaphore timeout
        }
    }
    finally
    {
        semaphore.Release();
    }
    

    A word of caution, unlike the Semaphore class, SemaphoreSlim works for synchronization within a single app but is not suitable for system wide inter-process synchronization.

  • JKnottJKnott Member ✭✭✭
    edited February 22

    Sorry, posted this to the wrong thread. please delete this

Sign In or Register to comment.