private void TriggerIngestion(IList <Log> logs, State stateSnapshot, string batchId) { // Before sending logs, trigger the sending event for this channel if (SendingLog != null) { foreach (var eventArgs in logs.Select(log => new SendingLogEventArgs(log))) { _mutex.Unlock(); SendingLog?.Invoke(this, eventArgs); _mutex.Lock(stateSnapshot); } } // If the optional Install ID has no value, default to using empty GUID var installId = MobileCenter.InstallId.HasValue ? MobileCenter.InstallId.Value : Guid.Empty; var serviceCall = _ingestion.PrepareServiceCall(_appSecret, installId, logs); serviceCall.ServiceCallFailedCallback = exception => { serviceCall.Dispose(); HandleSendingFailure(batchId, exception); }; serviceCall.ServiceCallSucceededCallback = async() => { serviceCall.Dispose(); if (!_stateKeeper.IsCurrent(stateSnapshot)) { return; } try { await _storage.DeleteLogsAsync(Name, batchId).ConfigureAwait(false); } catch (StorageException e) { MobileCenterLog.Warn(MobileCenterLog.LogTag, $"Could not delete logs for batch {batchId}", e); } try { await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); var removedLogs = _sendingBatches[batchId]; _sendingBatches.Remove(batchId); if (SentLog != null) { foreach (var log in removedLogs) { _mutex.Unlock(); SentLog?.Invoke(this, new SentLogEventArgs(log)); _mutex.Lock(stateSnapshot); } } CheckPendingLogs(); } catch (StatefulMutexException) { } finally { _mutex.Unlock(); } }; serviceCall.Execute(); }