You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The AddPackageAsync, RemovePackageAsync, and StagePackageAsync methods in the PackageManager class occasionally fail to complete, causing the application to be indefinitely stuck in a waiting state. This issue is related to the one reported in CsWinRT issue #1720, but we have identified additional problematic methods in PackageManager. I won't be surprised if all PackageManager async methods to suffer from this issue, so far all methods that we attempted to use are buggy.
How to Reproduce
Compile the provided code in Release mode. We haven't tried Debug but from our previous experience with CsWinRT issue #1720 I might guess this is only Release build issue.
Execute the code, which repeatedly calls the StagePackageAsync, RegisterPackageByFamilyNameAsync, and RemovePackageAsync methods in a loop.
Observe that the task returned by StagePackageAsync frequently fails to complete, although RemovePackageAsync is also occasionally affected. When this happens a timeout exception is thrown, because of the CircuitBreaker. If you remove the CircuitBreaker the loop will be stuck on the await forever.
Observations
The issue typically reproduces at least once in every 500 iterations. Some machines exhibiting the problem more frequently than others.
Attaching a debugger reveals a worker thread perpetually waiting for task completion.
Attempts to resolve this by synchronously calling the async methods using GetAwaiter().GetResult() were unsuccessful.
The problem occurs on both Windows 10 and Windows 11 machines across various versions of the microsoft.windows.sdk.net.ref NuGet package.
usingSystem;usingWindows.Management.Deployment;namespaceTestPackageInstall{internalclassProgram{staticasyncTaskMain(string[]args){stringtimestamp=DateTime.Now.ToString("HH:mm:ss");intnumberOfSuccessfullInstallation=0;intnumberOfFailedInstallationWithTimeout=0;intnumberOfFailedInstallationUnknown=0;while(true){try{// Create an instance of PackageManagerPackageManagerpackageManager=newPackageManager();// Get the current time as a string in the format HH:MM:SStimestamp=DateTime.Now.ToString("HH:mm:ss");// Print the log messages with the timestampConsole.WriteLine($"[{timestamp}] Number of successful installations: {numberOfSuccessfullInstallation}");Console.WriteLine($"[{timestamp}] Number of failed installations, because of timeout: {numberOfFailedInstallationWithTimeout}");Console.WriteLine($"[{timestamp}] Number of failed installations: {numberOfFailedInstallationUnknown}");Console.WriteLine($"[{timestamp}] Staging...");// Define the URI for the packagevaruri=newUri("https://storage.googleapis.com/ms-apps-bucket-exp/update/com.mobisystems.windows.appx.mobipdf/10.0.57990/full/MobiPDF.Package_10.0.57990.0_x64.msix");// Attempt to stage the packageCircuitBreakercircuitBreaker=newCircuitBreaker();awaitcircuitBreaker.ExecuteAsync(async()=>awaitpackageManager.StagePackageAsync(uri,null).AsTask().ConfigureAwait(false),TimeSpan.FromMinutes(15)).ConfigureAwait(false);timestamp=DateTime.Now.ToString("HH:mm:ss");Console.WriteLine($"[{timestamp}] Register...");// Register the package by family nameawaitpackageManager.RegisterPackageByFamilyNameAsync("MobiSystems.MobiPdf_bvgb55c3tfatp",null,DeploymentOptions.ForceTargetApplicationShutdown,packageManager.GetDefaultPackageVolume(),null).AsTask(newConsoleDeploymentProgress("RegisterPackage")).ConfigureAwait(false);// Increment the success counternumberOfSuccessfullInstallation++;timestamp=DateTime.Now.ToString("HH:mm:ss");Console.WriteLine($"[{timestamp}] Uninstall...");// Remove the packageawaitpackageManager.RemovePackageAsync("MobiSystems.MobiPdf_10.0.57990.0_x64__bvgb55c3tfatp").AsTask(newConsoleDeploymentProgress("RemovePackage")).ConfigureAwait(false);}catch(TimeoutException){timestamp=DateTime.Now.ToString("HH:mm:ss");Console.WriteLine($"*********************************************************");Console.WriteLine($"*********************************************************");Console.WriteLine($"*********************************************************");Console.WriteLine($"*********************************************************");Console.WriteLine($"*********************************************************");Console.WriteLine($"*********************************************************");numberOfFailedInstallationWithTimeout++;}catch(Exceptionex){timestamp=DateTime.Now.ToString("HH:mm:ss");Console.WriteLine($"[{timestamp}] Exception: {ex.Message}");numberOfFailedInstallationUnknown++;}timestamp=DateTime.Now.ToString("HH:mm:ss");// Clear the console for the next iterationConsole.WriteLine($"[{timestamp}] ===============================================================");}}publicclassConsoleDeploymentProgress:IProgress<DeploymentProgress>{privatereadonlystringoperationType;publicConsoleDeploymentProgress(stringoperationType){this.operationType=operationType;}publicvoidReport(DeploymentProgressvalue){// Get the current time as a string in the format HH:MM:SSstringtimestamp=DateTime.Now.ToString("HH:mm:ss");Console.WriteLine($"[{timestamp}] {operationType} progress: {value.percentage}");}}publicclassCircuitBreaker{publicasyncTask<T>ExecuteAsync<T>(Func<Task<T>>asyncMethod,TimeSpantimeout){using(varcts=newCancellationTokenSource()){vartask=asyncMethod();varcompletedTask=awaitTask.WhenAny(task,Task.Delay(timeout,cts.Token)).ConfigureAwait(false);if(completedTask==task){// Cancel the delay task if the main task completes firstcts.Cancel();returnawaittask.ConfigureAwait(false);// Unwrap and return the result}else{thrownewTimeoutException("The operation has timed out.");}}}}}}
Example call stack when the method freezes
The text was updated successfully, but these errors were encountered:
We have identified additional details regarding this issue. By passing a CancellationToken to the affected methods, the freezing problem is resolved. Here is an example of how to implement this:
Using this approach, we conducted thousands of package installations with AddPackageAsync and StagePackageAsync, and none of these operations froze, unlike when they were executed without a CancellationToken. We hope this information helps in addressing the issue or provides a viable workaround.
The AddPackageAsync, RemovePackageAsync, and StagePackageAsync methods in the PackageManager class occasionally fail to complete, causing the application to be indefinitely stuck in a waiting state. This issue is related to the one reported in CsWinRT issue #1720, but we have identified additional problematic methods in PackageManager. I won't be surprised if all PackageManager async methods to suffer from this issue, so far all methods that we attempted to use are buggy.
How to Reproduce
Compile the provided code in Release mode. We haven't tried Debug but from our previous experience with CsWinRT issue #1720 I might guess this is only Release build issue.
Execute the code, which repeatedly calls the StagePackageAsync, RegisterPackageByFamilyNameAsync, and RemovePackageAsync methods in a loop.
Observe that the task returned by StagePackageAsync frequently fails to complete, although RemovePackageAsync is also occasionally affected. When this happens a timeout exception is thrown, because of the CircuitBreaker. If you remove the CircuitBreaker the loop will be stuck on the await forever.
Observations
The issue typically reproduces at least once in every 500 iterations. Some machines exhibiting the problem more frequently than others.
Attaching a debugger reveals a worker thread perpetually waiting for task completion.
Attempts to resolve this by synchronously calling the async methods using GetAwaiter().GetResult() were unsuccessful.
The problem occurs on both Windows 10 and Windows 11 machines across various versions of the microsoft.windows.sdk.net.ref NuGet package.
Code Sample
Example call stack when the method freezes
The text was updated successfully, but these errors were encountered: