CmlLib
English (v4)
English (v4)
  • 🧊CmlLib Projects
  • 🚀CmlLib.Core
    • Home
    • Getting Started
      • Minecraft Launcher
      • Minecraft Path
      • Versions
      • Launch Options
      • Event Handling
    • Login and Sessions
      • Microsoft Xbox Account
      • Offline Account
    • More APIs
      • MinecraftLauncherParameters
      • Rules
      • FileExtractor
      • GameInstaller
      • Java
    • Mod Loader Installers
      • Forge Installer
      • Fabric Installer
      • Quilt Installer
      • LiteLoader Installer
    • Utilities
      • Minecraft Changelogs
    • Resources
      • FAQ
      • Known Issues
      • Sample Launcher
      • License
  • 🔓Auth.Microsoft
    • Home
    • CmlLib.Core.Auth.Microsoft
      • JELoginHandler
      • JELoginHandlerBuilder
      • JEAuthenticator
      • Authentication with MSAL
    • XboxAuthNet.Game
      • OAuth
      • XboxAuth
      • XboxAuthException
      • AccountManager
      • Accounts
    • XboxAuthNet.Game.Msal
      • ClientID
      • MsalClientHelper
      • OAuth
    • CmlLib.Core.Bedrock.Auth
    • Resources
  • 🌐MojangAPI
    • Home
    • Mojang API
    • SecurityQuestion
  • ⚒️Installer.Forge
    • Home
    • Supported Versions
    • Getting Started
    • MForge
    • ForgeVersionLoader
Powered by GitBook
On this page
  • Example (with IProgress)
  • Example (with Event handler)
  • Performance Tips
Edit on GitHub
  1. CmlLib.Core
  2. Getting Started

Event Handling

Show installer progress to user

The game installer provides two types of event:

  • FileProgress indicates the name, type, and number of files in progress.

  • ByteProgress indicates the size of files processed / the size of all files in bytes.

And there are two ways to register an event handler:

  • Pass IProgress<> to the method of the game installer.

  • Register event handler. (will be invoked on the current SynchronizationContext, so it is safe to access UI components)

If the IProgress<> is passed to the method, any event handlers will be ignored.

Example (with IProgress)

var launcher = new MinecraftLauncher();
await launcher.InstallAsync(
    "1.20.4", 
    new Progress<InstallerProgressChangedEventArgs>(e =>
    {
        Console.WriteLine("Name: " + e.Name);
        Console.WriteLine("EventType: " + e.EventType);
        Console.WriteLine("TotalTasks: " + e.TotalTasks);
        Console.WriteLine("ProgressedTasks: " + e.ProgressedTasks);
    }),
    new Progress<ByteProgress>(e =>
    {
        Console.WriteLine("TotalBytes: " + e.TotalBytes);
        Console.WriteLine("ProgressedBytes: " + e.ProgressedBytes);
        Console.WriteLine("Percentage: " + e.ToRatio() * 100);
    }),
    CancellationToken.None);

Example (with Event handler)

var launcher = new MinecraftLauncher();
launcher.FileProgressChanged += (_, e) =>
{
    Console.WriteLine("Name: " + e.Name);
    Console.WriteLine("EventType: " + e.EventType);
    Console.WriteLine("TotalTasks: " + e.TotalTasks);
    Console.WriteLine("ProgressedTasks: " + e.ProgressedTasks);
};
launcher.ByteProgressChanged += (_, e) =>
{
    Console.WriteLine("TotalBytes: " + e.TotalBytes);
    Console.WriteLine("ProgressedBytes: " + e.ProgressedBytes);
    Console.WriteLine("Percentage: " + e.ToRatio() * 100);
};
await launcher.InstallAsync("1.20.4", CancellationToken.None);

Performance Tips

FileProgress is called very frequently (4000 to 8000 times at each launch), so if you put time-consuming tasks in the event handler, it can affect the performance of your program. ByteProgress, on the other hand, is only called 3-4 times per second.

So if you use an event handler in a console app, you'll be making a lot of calls to the ThreadPool. This can have a bad impact on the performance of your application, so either don't use FileProgress, or implement IProgress, which doesn't use ThreadPool. The library provides SyncProgress<T>, which runs the handler directly on the thread that called the event. SyncProgress<T> should not directly access the UI and should contain as little code as possible.

// example
IProgress<InstallerProgressChangedEventArgs> fileProgress = new SyncProgress<InstallerProgressChangedEventArgs>(e => 
{ 
    Console.WriteLine($"{e.ProgressedTasks} / {e.TotalTasks}");
});
PreviousLaunch OptionsNextLogin and Sessions

Last updated 4 months ago

When you register an event handler, it is internally converted to a new Progress<T>(handler). will have different behavior depending on the current SynchronizationContext. If it's a WinForm or WPF app, the handler's code will run in the UI thread, and if it's a console app, it will run in the ThreadPool.

🚀
Progress<T>