Avalonia
Avalonia copied to clipboard
X11: System.Exception: Unable to initialize GTK on separate thread
Describe the bug The exception in the title is thrown when opening a file dialog.
To Reproduce Create a new project using the Avalonia .NET Core App template. (NOT THE MVVM ONE). Here's the relevant code that triggers the exception:
<!-- MainWindow.axaml -->
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="JGCodes.AvaloniaTest.MainWindow"
Title="Avalonia Test">
<Button Name="SpecialButton" Click="OnButtonClick">Open, sesame!</Button>
</Window>
// MainWindow.axaml.cs
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace JGCodes.AvaloniaTest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public async void OnButtonClick(object sender, RoutedEventArgs e)
{
OpenFileDialog ofd = new();
await ofd.ShowAsync(this);
}
}
}
Run the project, click the button, and receive the above exception.
Expected behavior A file dialog should appear.
Desktop (please complete the following information):
- OS: Linux (ArcoLinux, KDE, XWayland)
- Version 0.10.17
Additional context N/A
Please check if you have libgtk-3.so.0
on your machine.
I do.
In the same case, execute await dlg.ShowAsync(parent: this); The UI is hang.
System: Ubuntu 22.04.1 LTS (GNU/Linux 5.15.57.1-microsoft-standard-WSL2 x86_64)
libgtk-3.so.0:
find . -name 'libgtk-3.so.0' -ls 33584910 0 lrwxrwxrwx 1 root root 21 5月 10 04:15 ./x86_64-linux-gnu/libgtk-3.so.0 -> libgtk-3.so.0.2404.29
We're getting 1-2 hits of this every day. Lots of snap users getting this issue.
Exception Unable to initialize GTK on separate thread / at Avalonia.X11.NativeDialogs.GtkSystemDialog.EnsureInitialized()
at Avalonia.X11.NativeDialogs.GtkSystemDialog.ShowFileDialogAsync(FileDialog dialog, Window parent)
at Avalonia.Controls.SaveFileDialog.ShowAsync(Window parent)
at Lunacy.Services.DialogService.SaveAsync(String defaultFileName, String[] fileTypeFilter) in /root/parts/lunacy/build/Lunacy/Lunacy.UI/Services/DialogService.cs:line 66
8.7.2.0 (Snapcraft), 370s, 557MB usage, fedora/ryan, Linux X64: Linux 5.17.5-300.fc36.x86_64 #1 SMP PREEMPT Thu Apr 28 15:51:30 UTC 2022, 4 cores
I've come to an idea that for linux - managed open/save file dialogs is a preferred option. This is an easy and almost 100% fix of this issue.
@Mikolaytis on 11.0 we use FreeDesktop/dBus picker by default, which should work better.
Got a similar problem Arch, KDE Plasma, OpenFileDialog just hangs.
FWIW, my workaround. below the ViewModel code, use binding to the view model. You do need kdialog installed on KDE systems for this to work.
<Button
Command="{Binding OpenFileCommand}"
Margin="0,0,10,0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Height="26"
FontSize="11"
Content="_Open..." />
Here the ViewModel code
public void OpenFileCommand()
{
var helper = new OpenDlgHelper();
var result = helper.GetFileName();
HexFile = string.IsNullOrEmpty(result) ? _prompt : result;
}
And here the helper class
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace QMK_Toolbox;
public class OpenDlgHelper
{
public StringBuilder sb { get; set; }
public string GetFileName()
{
RunProcessAsync("/usr/bin/kdialog", "--getopenfilename /home/").Wait();
return sb.ToString();
}
private async Task<int> RunProcessAsync(string command, string args)
{
sb = new StringBuilder();
using (var process = new Process
{
StartInfo =
{
FileName = command,
Arguments = args,
WorkingDirectory = Path.GetDirectoryName(command),
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true
},
EnableRaisingEvents = true
})
{
return await RunProcessAsync(process).ConfigureAwait(false);
}
}
private Task<int> RunProcessAsync(Process process)
{
var tcs = new TaskCompletionSource<int>();
process.Exited += (sender, e) =>
{
process.WaitForExit();
tcs.SetResult(process.ExitCode);
};
process.OutputDataReceived += ProcessOutput;
process.ErrorDataReceived += ProcessErrorOutput;
bool started = process.Start();
if (!started)
{
Debug.WriteLine($"Could not start process: {process}");
}
process.BeginOutputReadLine();
process.BeginErrorReadLine();
return tcs.Task;
}
private void ProcessOutput(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
{
sb.Append(e.Data);
}
}
private void ProcessErrorOutput(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
{
Debug.WriteLine(e.Data);
}
}
}
Should be fixed with 11.0 previews, as we use FreeDesktop dialogs instead, when available. Also, GTK initialization was changed, which might also solve old issue, if FreeDesktop is not available.
Please let us know if it's still a problem in 11.0 previews.