Browse Source

Win32: Run file picker on dedicated STA thread to avoid MTA deadlock (#21266)

* Run Win32 file picker on a dedicated thread to avoid MTA deadlock

* Add threading comment in Win32StorageProvider

---------

Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
pull/21292/head
Matt 5 months ago
committed by GitHub
parent
commit
8c3ddb105f
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 27
      src/Windows/Avalonia.Win32/Win32StorageProvider.cs

27
src/Windows/Avalonia.Win32/Win32StorageProvider.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Controls.Utils;
using Avalonia.Platform.Storage;
@ -96,7 +97,13 @@ namespace Avalonia.Win32
Func<string, TStorageItem> convert)
where TStorageItem : IStorageItem
{
return Task.Factory.StartNew(() =>
// TODO13: verify that we're on the correct dispatcher, matching other platforms' implementations.
// We should then be able to remove the dedicated thread and simply use IFileDialog directly (needs to be reconfirmed).
var tcs = new TaskCompletionSource<(IReadOnlyList<TStorageItem>, int)>(
TaskCreationOptions.RunContinuationsAsynchronously);
var thread = new Thread(() =>
{
IReadOnlyList<TStorageItem> result = [];
try
@ -179,7 +186,8 @@ namespace Avalonia.Win32
if ((uint)showResult == (uint)UnmanagedMethods.HRESULT.E_CANCELLED)
{
return (result, typeIndex);
tcs.SetResult((result, typeIndex));
return;
}
else if ((uint)showResult != (uint)UnmanagedMethods.HRESULT.S_OK)
{
@ -210,14 +218,23 @@ namespace Avalonia.Win32
result = [convert(singleResult)];
}
return (result, typeIndex);
tcs.SetResult((result, typeIndex));
}
catch (COMException ex)
{
var message = new Win32Exception(ex.HResult).Message;
throw new COMException(message, ex);
tcs.SetException(new COMException(message, ex));
}
}, TaskCreationOptions.LongRunning);
catch (Exception ex)
{
tcs.SetException(ex);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
return tcs.Task;
}
private static string? GetParsingName(IShellItem shellItem)

Loading…
Cancel
Save