Overview

BeepWait is a sophisticated loading and progress display form designed to provide visual feedback during long-running operations. It features an animated spinner, customizable title and messages, logo display, and real-time progress updates with thread-safe operation.

Built as a standalone form, BeepWait provides a professional loading experience with theme support, safe cross-thread updates, and comprehensive customization options. Perfect for file operations, data loading, network requests, and any operation that requires user patience.

Key Features

?? Animated Spinner

Smooth rotating spinner animation with customizable speed and appearance

?? Real-time Updates

Thread-safe progress updates with scrolling message display

??? Logo Integration

Company logo display with image path customization

?? Theme Support

Complete theming integration with automatic color application

?? Thread Safety

Safe cross-thread operations with proper invoke patterns

? Async Operations

Full async/await support for modern C# applications

Visual Preview

Loading Data...

Connecting to database...
Loading customer records...
Processing 1,234 items...
Applying filters...

BeepWait dialog showing animated spinner and progress messages

Basic Usage

Simple Wait Dialog

// Show a simple wait dialog
var waitForm = new BeepWait();
var args = new PassedArgs
{
    Title = "Processing...",
    Messege = "Please wait while we process your request.",
    ImagePath = "company-logo.png"
};

await waitForm.ShowAsync(args);

// Perform your long-running operation
await SomeTimeConsumingOperation();

// Close the wait dialog
await waitForm.CloseAsync();

With Progress Updates

// Create and show wait form with progress updates
var waitForm = new BeepWait();
var args = new PassedArgs
{
    Title = "Loading Data",
    Messege = "Initializing...",
    ImagePath = "app-icon.png"
};

// Show the form
await waitForm.ShowAsync(args);

try
{
    // Simulate a multi-step operation with progress updates
    for (int i = 0; i < 100; i++)
    {
        // Update progress with new message
        waitForm.UpdateProgress(i, $"Processing item {i + 1} of 100...");
        
        // Simulate work
        await Task.Delay(50);
    }
    
    waitForm.UpdateProgress(100, "Operation completed successfully!");
    await Task.Delay(1000); // Show completion message briefly
}
finally
{
    // Always close the wait form
    await waitForm.CloseAsync();
}

File Processing Example

public async Task ProcessLargeFile(string filePath)
{
    var waitForm = new BeepWait();
    var args = new PassedArgs
    {
        Title = "File Processing",
        Messege = "Reading file...",
        ImagePath = "file-icon.png"
    };

    await waitForm.ShowAsync(args);

    try
    {
        waitForm.UpdateProgress(0, "Opening file...");
        var lines = await File.ReadAllLinesAsync(filePath);
        
        waitForm.UpdateProgress(10, $"Processing {lines.Length} lines...");
        
        for (int i = 0; i < lines.Length; i++)
        {
            // Process each line
            ProcessLine(lines[i]);
            
            // Update progress every 100 lines
            if (i % 100 == 0)
            {
                int percentage = (i * 90) / lines.Length + 10; // 10-100%
                waitForm.UpdateProgress(percentage, 
                    $"Processed {i + 1} of {lines.Length} lines...");
            }
        }
        
        waitForm.UpdateProgress(100, "File processing completed!");
        await Task.Delay(500);
    }
    catch (Exception ex)
    {
        waitForm.UpdateProgress(0, $"Error: {ex.Message}");
        await Task.Delay(2000);
    }
    finally
    {
        await waitForm.CloseAsync();
    }
}

Properties

Core Properties

Property Type Description
Passedarguments PassedArgs Configuration object containing title, message, and image path
Title BeepLabel Main title label displayed at the top
messege RichTextBox Scrollable message area for progress updates
LogopictureBox BeepImage Logo/image display control

Animation Properties

Property Type Description
_spinnerImage BeepImage Spinner animation control
_rotationAngle float Current rotation angle of the spinner
_spinnerTimer Timer Timer controlling spinner animation speed

PassedArgs Structure

Property Type Description
Title string Dialog title text
Messege string Initial message text
ImagePath string Path to logo/icon image file

Methods

Main Operations

Method Parameters Returns Description
ShowAsync PassedArgs args Task<IErrorsInfo> Shows the wait form with specified configuration
CloseAsync - Task<IErrorsInfo> Closes the wait form after optional delay
UpdateProgress int progress, string text void Updates progress with new message (thread-safe)

Configuration Methods

Method Parameters Description
SetTitle string title Sets the dialog title text
SetText string text Sets the main message text
SetImage string imagePath Sets the logo/icon image

Animation Methods

Method Description
StartSpinner Starts the spinner animation
StopSpinner Stops the spinner animation
ApplyTheme Applies current theme to all child controls

Examples

Database Operation with Progress

public async Task> LoadCustomersAsync()
{
    var waitForm = new BeepWait();
    var args = new PassedArgs
    {
        Title = "Loading Customers",
        Messege = "Connecting to database...",
        ImagePath = "database-icon.png"
    };

    await waitForm.ShowAsync(args);
    var customers = new List();

    try
    {
        waitForm.UpdateProgress(10, "Establishing database connection...");
        using var connection = new SqlConnection(connectionString);
        await connection.OpenAsync();

        waitForm.UpdateProgress(25, "Executing customer query...");
        var command = new SqlCommand("SELECT * FROM Customers", connection);
        using var reader = await command.ExecuteReaderAsync();

        waitForm.UpdateProgress(50, "Reading customer data...");
        int customerCount = 0;
        
        while (await reader.ReadAsync())
        {
            customers.Add(new Customer
            {
                Id = reader.GetInt32("Id"),
                Name = reader.GetString("Name"),
                Email = reader.GetString("Email"),
                Phone = reader.GetString("Phone")
            });
            
            customerCount++;
            if (customerCount % 50 == 0)
            {
                waitForm.UpdateProgress(
                    50 + (customerCount * 40 / 1000), // Estimate progress
                    $"Loaded {customerCount} customers...");
            }
        }

        waitForm.UpdateProgress(95, "Finalizing data...");
        await Task.Delay(500); // Simulate final processing

        waitForm.UpdateProgress(100, $"Successfully loaded {customers.Count} customers!");
        await Task.Delay(1000);
    }
    catch (Exception ex)
    {
        waitForm.UpdateProgress(0, $"Error loading customers: {ex.Message}");
        await Task.Delay(3000);
        throw;
    }
    finally
    {
        await waitForm.CloseAsync();
    }

    return customers;
}

File Upload with Progress

public async Task UploadFileAsync(string filePath, string uploadUrl)
{
    var waitForm = new BeepWait();
    var fileInfo = new FileInfo(filePath);
    var args = new PassedArgs
    {
        Title = "File Upload",
        Messege = $"Preparing to upload {fileInfo.Name}...",
        ImagePath = "upload-icon.png"
    };

    await waitForm.ShowAsync(args);

    try
    {
        waitForm.UpdateProgress(5, "Validating file...");
        if (!fileInfo.Exists)
        {
            waitForm.UpdateProgress(0, "Error: File not found!");
            await Task.Delay(2000);
            return false;
        }

        waitForm.UpdateProgress(10, "Preparing upload request...");
        using var httpClient = new HttpClient();
        using var content = new MultipartFormDataContent();
        
        waitForm.UpdateProgress(20, "Reading file content...");
        var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
        var streamContent = new StreamContent(fileStream);
        content.Add(streamContent, "file", fileInfo.Name);

        waitForm.UpdateProgress(30, "Starting upload...");
        
        // Create progress tracking
        var progress = new Progress(bytesUploaded =>
        {
            var percentage = (int)((bytesUploaded * 60.0) / fileInfo.Length) + 30; // 30-90%
            waitForm.UpdateProgress(percentage, 
                $"Uploaded {FormatBytes(bytesUploaded)} of {FormatBytes(fileInfo.Length)}...");
        });

        var response = await httpClient.PostAsync(uploadUrl, content);
        
        waitForm.UpdateProgress(95, "Verifying upload...");
        response.EnsureSuccessStatusCode();
        
        waitForm.UpdateProgress(100, "Upload completed successfully!");
        await Task.Delay(1000);
        
        return true;
    }
    catch (Exception ex)
    {
        waitForm.UpdateProgress(0, $"Upload failed: {ex.Message}");
        await Task.Delay(3000);
        return false;
    }
    finally
    {
        await waitForm.CloseAsync();
    }
}

private string FormatBytes(long bytes)
{
    string[] sizes = { "B", "KB", "MB", "GB" };
    double len = bytes;
    int order = 0;
    while (len >= 1024 && order < sizes.Length - 1)
    {
        order++;
        len = len / 1024;
    }
    return $"{len:0.##} {sizes[order]}";
}

Batch Processing with Status Updates

public async Task ProcessOrdersAsync(List orders)
{
    var waitForm = new BeepWait();
    var args = new PassedArgs
    {
        Title = "Processing Orders",
        Messege = "Initializing batch processing...",
        ImagePath = "process-icon.png"
    };

    await waitForm.ShowAsync(args);

    try
    {
        var totalOrders = orders.Count;
        var processedOrders = 0;
        var errorCount = 0;

        waitForm.UpdateProgress(5, $"Starting batch processing for {totalOrders} orders...");

        foreach (var order in orders)
        {
            try
            {
                waitForm.UpdateProgress(
                    (processedOrders * 90) / totalOrders + 5, // 5-95%
                    $"Processing order {order.OrderNumber} ({processedOrders + 1} of {totalOrders})...");

                // Simulate order processing steps
                await ValidateOrder(order);
                waitForm.UpdateProgress(
                    (processedOrders * 90) / totalOrders + 5,
                    $"Validating payment for order {order.OrderNumber}...");

                await ProcessPayment(order);
                waitForm.UpdateProgress(
                    (processedOrders * 90) / totalOrders + 5,
                    $"Updating inventory for order {order.OrderNumber}...");

                await UpdateInventory(order);
                waitForm.UpdateProgress(
                    (processedOrders * 90) / totalOrders + 5,
                    $"Sending confirmation for order {order.OrderNumber}...");

                await SendConfirmation(order);
                
                processedOrders++;
            }
            catch (Exception ex)
            {
                errorCount++;
                waitForm.UpdateProgress(
                    (processedOrders * 90) / totalOrders + 5,
                    $"Error processing order {order.OrderNumber}: {ex.Message}");
                await Task.Delay(1000); // Brief pause to show error
            }
        }

        waitForm.UpdateProgress(100, 
            $"Batch processing completed! Processed: {processedOrders}, Errors: {errorCount}");
        await Task.Delay(2000);
    }
    catch (Exception ex)
    {
        waitForm.UpdateProgress(0, $"Batch processing failed: {ex.Message}");
        await Task.Delay(3000);
        throw;
    }
    finally
    {
        await waitForm.CloseAsync();
    }
}

Theming

BeepWait provides comprehensive theming with automatic application of theme colors and fonts to all child controls:

Theme Application

var waitForm = new BeepWait
{
    Theme = "DarkTheme"
};

// Theme automatically applies to:
// - Form background color
// - Title label styling
// - Message area colors
// - Spinner colors
// - Logo control theming

// Manual theme application
waitForm.ApplyTheme();

Theme Properties Applied

  • BackColor - Form background from theme
  • ForeColor - Text color from theme
  • Title theming - Title label uses theme fonts and colors
  • Message area - RichTextBox uses theme colors
  • Spinner colors - Animation colors match theme
  • Logo theming - BeepImage control theme application

Custom Theme Colors

// Create wait form with custom theme
var waitForm = new BeepWait();

// Apply theme before showing
waitForm.Theme = "CustomTheme";
waitForm.ApplyTheme();

// Or customize individual controls after theme application
waitForm.Title.ForeColor = Color.White;
waitForm.messege.BackColor = Color.FromArgb(30, 30, 30);
waitForm.messege.ForeColor = Color.LightGray;

Best Practices

?? Thread Safety

  • Use UpdateProgress: Always use UpdateProgress method for thread-safe message updates
  • Async operations: Use async/await pattern for all long-running operations
  • Proper disposal: Always call CloseAsync in finally blocks
  • UI thread: Ensure ShowAsync is called from the UI thread

?? Progress Updates

  • Meaningful messages: Provide clear, specific progress messages
  • Regular updates: Update progress frequently enough to show activity
  • Percentage tracking: Use the progress parameter for completion percentage
  • Error handling: Show clear error messages when operations fail

?? User Experience

  • Clear titles: Use descriptive titles that explain the operation
  • Appropriate imagery: Choose relevant icons/logos for the operation context
  • Reasonable delays: Don't show wait dialogs for very quick operations (<1 second)
  • Completion feedback: Show success/completion messages before closing

? Performance

  • Minimal updates: Don't update progress too frequently (avoid spam)
  • Batch operations: Group related operations for better user experience
  • Resource cleanup: Properly dispose of resources in finally blocks
  • Cancellation support: Consider adding cancellation tokens for long operations
?? Design Tip

Keep progress messages specific and informative. Instead of "Processing...", use "Processing order 5 of 20..." or "Uploading file (2.1 MB of 5.3 MB)..."

? Success Pattern

Always use try-catch-finally blocks with CloseAsync in the finally block to ensure the wait dialog is properly closed even if errors occur.

?? Thread Safety Warning

Never update UI controls directly from background threads. Always use the UpdateProgress method which handles cross-thread operations safely.