Azure / Xamarin - SyncContext.InitializeAsync Deadlock - sqlite

I have a Xamarin.Forms App which use Azure App Service with SQLLite Offline Sync.
When calling SyncContext.InitializeAsync a deadlock appears and the function InitializeAsync never finished.
In this Thread in found the solution: Azure/Xamarin Mobile App Hangs at SyncContext.InitializeAsync
This works:
System.Threading.Tasks.Task.Run(() => this.IDataProvider.IMobileServiceClient.SyncContext.InitializeAsync(localStore, _syncHandler)).Wait();
This not:
await this.IDataProvider.IMobileServiceClient.SyncContext.InitializeAsync(localStore, _syncHandler);
Whole function:
public override async System.Threading.Tasks.Task Init()
{
string storePath = System.IO.Path.Combine(Microsoft.WindowsAzure.MobileServices.MobileServiceClient.DefaultDatabasePath, localStoreName);
Microsoft.WindowsAzure.MobileServices.SQLiteStore.MobileServiceSQLiteStore localStore = new Microsoft.WindowsAzure.MobileServices.SQLiteStore.MobileServiceSQLiteStore(storePath);
localStore.DefineTable<CPM.Recruitment.Mobile.Freelancer.DataObjects.Entities.Promoter>();
System.Threading.Tasks.Task.Run(() => this.IDataProvider.IMobileServiceClient.SyncContext.InitializeAsync(localStore, _syncHandler)).Wait();
//await this.IDataProvider.IMobileServiceClient.SyncContext.InitializeAsync(localStore, _syncHandler);
_promoters = new Azure.AppService.DataObjects.Client.Sync.List<CPM.Recruitment.Mobile.Freelancer.DataObjects.Entities.Promoter>(this, this.IDataProvider.IMobileServiceClient.GetSyncTable<CPM.Recruitment.Mobile.Freelancer.DataObjects.Entities.Promoter>());
}
But why? I dont want to use Wait();

The differences between await and Wait method are:
await means the current task will be executed in a separated thread asynchronously and the calling thread won't be blocked. If the calling thread is UI thread. the UI thread will continue to run other operations.
Wait method are synchronization method. It causes the calling thread to wait until the current task has completed. If the calling thread is UI thread, UI operations will be blocked.
It seems that a deadlock will be caused if you use await to run the task which will not block UI thread.

Related

Facing a rare issue in async method - .net core 3.1

we developed an API using .net core 3.1 with async methods.
here the issue is current object value has been overwritten by the subsequent request value.
example:
async Task function(request)
{
var devUser = GetUserDetail(request.userType, request.userId);
var response = await ExecureRequest(request, devUser.name);
}
in the above example
"devUser" object value of Api Request 1 call has been overwritten by the Api Request 2 call
is there any possibilities get this issue in async methods.?
please share me your experience and comments.
The async keyword turns a method into an async method, which allows you to use the await keyword in its body. When the await keyword is applied, it suspends the calling method and yields control back to its caller until the awaited task is complete. await can only be used inside an async method.
"devUser" local variable is no possibilities get this issue in async methods.

Is it okay to modify application state in a firestore transaction on the server?

The docs state
Do not modify application state inside of your transaction functions. Doing so will introduce concurrency issues, because transaction functions can run multiple times and are not guaranteed to run on the UI thread.
When using the admin SDK there'll be pessimistic concurrency control and I don't need to think about a UI thread. Does that mean its okay to modify state in admin SDK transactions?
Transactions may fail to commit for various reasons. In such cases the SDK can retry the transaction up to 5 times, causing the update function to execute multiple times (see API docs). So it's still not a good idea to do state changes in the body of the transaction update. It's best to observe the transaction commit status before making a state change:
try {
await db.runTransaction(async (t) => {
const doc = await t.get(cityRef);
const newPopulation = doc.data().population + 1;
t.update(cityRef, {population: newPopulation});
});
console.log('Transaction success!');
// DO STATE CHANGES HERE
} catch (e) {
console.log('Transaction failure:', e);
}

LoadBalancingChannel exception on DocumentClient.Dispose()

We have hit an issue where after using CosmosDb, an exception occurs if we try to dispose of the DocumentClient shortly after. Waiting a few seconds before disposing causes no exceptions. We have confirmed that we are using await with every asynchronous call.
Psuedo-code:
using(DocumentClient documentClient = new DocumentClient(...params)) {
IOrderedQueryable<T> query = this.documentClient.CreateDocumentQuery<T>(...params);
IList<T> documents;
using (IDocumentQuery<T> documentQuery = query.AsDocumentQuery()) {
documents = (await documentQuery.ExecuteNextAsync<T>()).ToList();
}
// Processing...
}
The exception states:
LoadBalancingChannel rntbd://[ip].documents.azure.com:[port]/ in use
The API that makes the call successfully returns before DocumentClient.Dispose is called (all of the documents are correctly returned).
Has anyone seen this exception before? A search revealed no hits.
It can happen if the DocumentClient is disposed while pending requests. this was addressed in SDK version 2.2.2, please upgrade to latest SDK version.

Maintain dependency object instance within the thread

Need help on below issue, I have below method:
public IHttpActionResult Test()
{
Task.Run(() => DoTheStuff())
Return Ok()
}
Note: Here I don't want to use async/await keyword, as I don't care about the result of DoTheStuff() method. I just need to open one thread and execute the code.
DoTheStuff() method refers the objects which are injected through dependency injection (Autofac). and in Module.Config I have registered all the required dependencies with lifetimescope.
Below issue I am facing call to Task.Run(() => DoTheStuff()) starts new thread executing DoTheStuff() method.
At the same time Test() method completes it execution with return Ok(), but DoTheStuff method is still running asynchronously.
With execution of Test() method, the registered dependencies gets disposed, and DoTheStuff() method throws below exception:
Nested lifetime cannot be created from the LifetimeScope as it has
already been disposed
Can someone please let me know how to maintain dependency object instance within the thread?
I can see a couple options.
Extract DoTheStuff into its own service. Register the services that you're injecting and using in DoTheStuff as InstancePerDependency so that the service gets its own instance. See https://autofaccn.readthedocs.io/en/latest/lifetime/instance-scope.html.
Add a Wait:
var t = Task.Run(() => DoTheStuff());
t.Wait();
return Ok();
Let me know if neither of those works.

Wait for async thrift requests to complete

I am invoking multiple async calls of thrift from my code. I would like to wait
for all of them to complete before going on with my next stage.
for (...) {
TNonblockingTransport transport = new TNonblockingSocket(host, port);
TAsyncClientManager clientManager = new TAsyncClientManager();
TProtocolFactory protocolFactory = new TBinaryProtocol.Factory();
AsyncClient c = new AsyncClient(protocolFactory, clientManager, transport);
c.function(params, callback);
}
// I would like to wait for all the calls to be complete here.
I can have a countdown in the callback like wait/notify and get this done. But does the thrift system allow a way for me to wait on my async function call, preferably with a timeout ?
I didnt see any in the TAsyncClientManager or in the AsyncClient. Please help.
Given that it was not possible to do this, I used the sync api client and managed the launch and wait using executors and launchAll. I am leaving this as my answer for people to have an alternative.

Resources