C# Windows app: Uploading database backups to Google Drive?

Hey everyone! I’m trying to make a C# Windows app that can upload database backup files to Google Drive. I’ve got most of the code working, but I’m running into a weird error when I try to update the UI:

private void UpdateUI(string message)
{
    if (InvokeRequired)
    {
        Invoke(new Action<string>(UpdateUI), message);
    }
    else
    {
        statusLabel.Text = message;
    }
}

private async Task UploadBackupAsync(string filePath)
{
    var service = await GetDriveServiceAsync();
    var fileInfo = new FileInfo(filePath);
    var fileMetadata = new Google.Apis.Drive.v3.Data.File()
    {
        Name = fileInfo.Name,
        Description = "Database backup"
    };

    using (var stream = new FileStream(filePath, FileMode.Open))
    {
        var request = service.Files.Create(fileMetadata, stream, fileInfo.Extension);
        request.Fields = "id";
        var progress = await request.UploadAsync();
        
        if (progress.Status == UploadStatus.Completed)
        {
            UpdateUI($"Upload complete! File ID: {request.ResponseBody.Id}");
        }
    }
}

Any ideas on how to fix this? Thanks in advance!

Having worked on similar projects, I can offer some insights. The issue you’re facing is likely related to thread synchronization. A more robust approach would be to use a SynchronizationContext or a custom TaskScheduler to manage UI updates. Here’s a snippet that’s proven effective in my experience:

private readonly SynchronizationContext _syncContext;

public Form1()
{
    InitializeComponent();
    _syncContext = SynchronizationContext.Current;
}

private void UpdateUI(string message)
{
    _syncContext.Post(_ => statusLabel.Text = message, null);
}

This method ensures that UI updates are always performed on the UI thread, eliminating cross-thread operation exceptions. Additionally, consider implementing a cancellation token for long-running operations to improve responsiveness and allow users to cancel uploads if needed.

I’ve dealt with similar issues when building backup solutions for clients. The problem you’re facing is likely due to the UI update being called from a background thread. Here’s what worked for me:

Instead of using Invoke directly, try using BeginInvoke. This queues the UI update on the UI thread without blocking:

private void UpdateUI(string message)
{
    if (InvokeRequired)
    {
        BeginInvoke(new Action(() => statusLabel.Text = message));
    }
    else
    {
        statusLabel.Text = message;
    }
}

Also, consider using a progress reporter to handle UI updates more smoothly:

private async Task UploadBackupAsync(string filePath, IProgress<string> progress)
{
    // ... existing code ...
    
    var request = service.Files.Create(fileMetadata, stream, fileInfo.Extension);
    request.Fields = "id";
    request.ProgressChanged += (IUploadProgress p) => progress.Report($"Uploaded {p.BytesSent} bytes");
    var result = await request.UploadAsync();
    
    // ... rest of the code ...
}

This approach has worked well in my projects, providing smoother UI updates and better responsiveness.

yo, i’ve been there! try using Task.Run() to run ur upload on a separate thread, then use a progress handler to update the UI. somethin like this:

task.run(async () => {
await UploadBackupAsync(filePath, new Progress(s => UpdateUI(s)));
});

this way ur UI stays responsive n u avoid those nasty cross-thread exceptions. good luck!