Docs Menu

Sync Changes Between Devices - .NET SDK

On this page

  • Prerequisites
  • Sync Data
  • Pause or Resume a Sync Session
  • Monitor Sync Progress and Status
  • Wait for Changes to be Uploaded or Downloaded
  • Monitor Sync Progress
  • Get Connection State Changes
  • Handle Sync Errors
  • Set the Client Log Level
  • Customize the Logging Function

Before you can access a synced realm from the client, you must:

The syntax to read and write on a synced realm is identical to the syntax for non-synced realms. While you work with local data, a background thread efficiently integrates, uploads, and downloads changesets.

When Using Sync, Avoid Writes on the Main Thread

The fact that Realm performs sync integrations on a background thread means that if you write to your realm on the main thread, there's a small chance your UI could appear to hang as it waits for the background sync thread to finish a write transaction. Therefore, it's a best practice never to write on the main thread when using Device Sync.

The following code creates a new Task object and writes it to the realm:

var testTask = new Task
Name = "Do this thing",
Status = TaskStatus.Open.ToString(),
Partition = "myPart"
realm.Write(() =>
See also:

Opening a synced realm starts a Sync Session. To pause synchronization for a specific session, you can call the Stop() method on the session.

When you then call the Start() method on the paused session, the Sync session resumes.

Each session is independent

You must manually call the Stop() and Start() methods for each realm whose Sync session you want to pause and restart. The sync state of one session has no impact on other open sessions.

The following code block demonstrates calling the Stop() and Start() methods:

var session = realm.SyncSession;

You may want to know the status of Sync operations in your app. For example, you might want specific code to run only after all of the data is synced with App Services. You might also want to provide users with the status of Sync operations.

You can set up your Sync session to wait for changes to be uploaded or downloaded. You can also configure your Sync session to notify when the Sync connection status changes.

To asynchronously wait for your changes to be completed, get the sync session from the Realms.Sync.SyncSession property, and then call the session.WaitForUploadAsync() or session.WaitForDownloadAsync() methods. For example:

using Realms.Sync;
var realm = Realm.GetInstance(config);
await realm.SyncSession.WaitForDownloadAsync();

To monitor Sync progress, get the sync session from the Realms.Sync.SyncSession property, then add a progress notification by calling the session.GetProgressObservable() method.

The session.GetProgressObservable method takes in the following two parameters:

  • A ProgressDirection parameter that can be set to Upload or Download.
  • A ProgressMode parameter that can be set to ReportIndefinitely for the notifications to continue until the callback is unregistered, or ForCurrentlyOutstandingWork for the notifications to continue until only the currently transferable bytes are synced.

When you Subscribe to the notifications, you receive a SyncProgress object that provides the total number of transferrable bytes and the remaining bytes to be transferred.


The number of transferred and transferable bytes are only estimates. The Sync changesets are compressed with gzip before transmitting, so the actual size of transmitted bytes will be smaller than the reported number of both transferable and transferred bytes.


In the following example, we subscribe to a progress observable on the session to listen for upload events indefinitely. When this callback is triggered, it prints the number of transferred bytes and the number of transferable bytes to the console.

var session = realm.SyncSession;
var token = session.GetProgressObservable(ProgressDirection.Upload,
.Subscribe(progress =>
Console.WriteLine($@"transferred bytes:
Console.WriteLine($@"transferable bytes:

Once you no longer wish to receive notifications, unregister the token by using token.Dispose()


The SDK optimizes download speeds by combining multiple changesets into a single download message, up to 16 MB. Since the progress callback is only invoked once before and after a download message is processed, this means that you'll likely see transferredBytes change in increments of roughly 16 MB rather than continuously as the message is being downloaded.

To get the connection state of a SyncSession, set an event handler on the PropertyChanged event. The event handler is a standard .NET PropertyChangedEventHandler delegate that takes in a sender object and PropertyChangedEventArgs object. In the event handler, cast the sender to a Session object and check if the event argument's PropertyName property is Session.ConnectionState. You can then get the ConnectionState value, which will be one of the following:

  • Connecting
  • Connected
  • Disconnected

The following code demonstrates setting the event handler, casting the session object, and checking the Sync status:

public async Task SetupRealm()
var appConfig = new AppConfiguration(myRealmAppId);
app = App.Create(appConfig);
user = app.LogInAsync(Credentials.Anonymous()).Result;
config = new PartitionSyncConfiguration("myPartition", user);
var realm = Realm.GetInstance(config);
var session = realm.SyncSession;
session.PropertyChanged += SyncSessionPropertyChanged;
catch (Exception ex)
private void SyncSessionPropertyChanged(object sender, PropertyChangedEventArgs e)
if (e.PropertyName == nameof(Session.ConnectionState))
var session = (Session)sender;
var currentState = session.ConnectionState;
if (currentState == ConnectionState.Connecting)
//session is connecting
if (currentState == ConnectionState.Connected)
//session is connected
if (currentState == ConnectionState.Disconnected)
//session has been disconnected

Device Sync represents errors via SessionExceptions. In addition to the standard exception properties, you have access to an ErrorCode that contains information about the type of the error and allows you to have strongly typed handling logic.

Session.Error += (session, errorArgs) =>
var sessionException = (SessionException)errorArgs.Exception;
switch (sessionException.ErrorCode)
case ErrorCode.AccessTokenExpired:
case ErrorCode.BadUserAuthentication:
// Ask user for credentials
case ErrorCode.PermissionDenied:
// Tell the user they don't have permissions to work with that Realm
case ErrorCode.Unknown:
// Likely the app version is too old, prompt for update
// ...
Additional Exception Information

For security reasons, App Services may send only a minimal amount of information about an exception, but the server-side logs will contain more details. In these cases, the HelpLink property on the exception contains a link to the associated log entry.

To control which messages are logged by the client logger, use LogLevel:

Logger.LogLevel = LogLevel.Debug;

To diagnose and troubleshoot errors while developing your application, set the log level to debug or trace. For production deployments, decrease the log level for improved performance.

To set a custom logger function, set Logger.Default to a custom Logger function.

using Realms.Logging;
Logger.LogLevel = LogLevel.All;
// customize the logging function:
Logger.Default = Logger.Function(message =>
// Do something with the message
←  Link User Identities - .NET SDKFlexible Sync - .NET SDK →
Give Feedback
© 2022 MongoDB, Inc.


  • Careers
  • Investor Relations
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2022 MongoDB, Inc.