Open RRQM opened 1 day ago
I think the async operations shouldn't be fone before the ui starts otherwise the user may get confused due to long loading times.
Thanks for your reply.
But I think adding a new async initialization might be a better solution. As for your suggestion that there shouldn't be a time-consuming effect when the program loads, I think this should be the choice of other developers, not the limitation of the framework itself.
Taking a step back, a lot of the time, the internet connection is also very fast and doesn't affect the loading of the program.
But since his connection is asynchronous, I should finish the asynchronous build when initializing. can be injected into the container, but it's clear that this isn't possible with the current synchronous approach.
Actually, if it's in a desktop program, I can just use task.GetAwaiter().GetResult();
to wait for the async to complete.
But in the web, this method will not be allowed to be used.
So, I think it's essential for the current CSharp ecosystem to load programs, or other rewritable functions, and provide asynchronous related methods.
Blazor, for example, provides a lot of synchronous and asynchronous APIs.
Finally, I looked at the relevant source code and found that it was actually not very difficult to add asynchronous initialization.
The most important thing is that it doesn't break the existing API. It's just a new addition.
The problem with having Initialize
or OnFrameworkInitializationCompleted
become async is people will use them for long and/or unreliable operations. For file I/O involving small config files, sync I/O is still usable because the UI thread lacks pressing concerns because there's no visual yet.
What you can do is isolate you app into two parts: a very tiny part without DI and the real app with DI. The part without DI will be shown first and show a splash window (or view if mobile). This will show while loading and you will also construct your IoC container from this part. Once loaded, you then you navigate to your main app's view using the IoC just built and everything is the same as before. A third-party library could be made for this, but it might be too opinionated to include within Avalonia.
There's likely a smart way to do this without an isolated splash screen, but your main window will have similar restrictions until DI kicks in to allow population/creation of child views. There's probably some work here to develop/teach better patterns.
I see what you mean, but I still don't think it should be limited by frameworks.
In short, if you support asynchronous methods, you won't have any problems performing synchronization, but if you call asynchronous methods in synchronous methods, unpredictable problems will occur.
Please rethink the KISS principle.
"Async void" is bad primarily for two reasons:
Error handling can be dangerous.
I am going to move second one out of the discussion quickly. In XAML frameworks task continuation goes to Dispatcher synchronization context by default. Which also means unhandled exceptions will go to Dispatcher thread and can be handled there. It won't crash any secondary threads but will go directly to the main thread. In case of app initialization, result is practically the same. The same goes to event handlers, which often are "async void" too. Although, I still wouldn't recommend relying on "async void" when you can avoid it.
You can't await this method.
While it's true, Avalonia initialization code cannot be fully asynchronous:
GetAwaiter().GetResult()
will cause deadlocks, as app needs UI sync.context inside.Meaning, we only can make App.Initialize()
async Task without actually waiting for it... Which exactly how it is now.
This code has another issue though:
await client.ConnectAsync();
// ...
AvaloniaXamlLoader.Load(this);
This code might cause issues with the fact that App.xaml
content was ignored at a time AppBuilder completed initialization. And only was completed at some point later. All styles and app properties initialization will be delayed.
I would rather recommend using OnFrameworkInitializationCompleted
as an async void
entrypoint.
Blazor, for example, provides a lot of synchronous and asynchronous APIs.
With Browser in general it's a special story. Browser C# apps don't have a "true" Main method. It's just a method, which is executed at some point after web page processed main JS script, and browser doesn't wait for this initialization to be completed before rendering anything.
Can't you just rewrite this to use a factory method? EG
public class WebSocketDmtpClientFactory {
private static IWebSocketDmtpClient Instance { get; set; }
public async Task<IWebSocketDmtpClient> GetClientAsync() {
if (Instance is not null} {
return instance;
}
var client = new WebSocketDmtpClient();
await client.SetupAsync(new TouchSocketConfig()
.SetDmtpOption(new DmtpOption { VerifyToken = "Dmtp" })
.ConfigurePlugins(a => a.UseDmtpRpc())
.SetRemoteIPHost("ws://localhost:5043/WebSocketDmtp"));
Instance = client;
return client
}
}
....
services.AddSingleton<WebSocketDmtpClientFactory>();
Obviously you still can't do async injection with this though.
There is also a discussion here about adding real async support for MSDI:
Is your feature request related to a problem? Please describe.
The current Application class only has the Initialize synchronization function.
If I have some business that requires network communication and need to register communication components in the IOC container, then there will be problems.
Firstly, the connection of communication components is asynchronous, for example:
Task ConnectAsync()
And container registration must be synchronized, so I had to initialize the components in advance and register them as singleton.
For example:
But obviously, the use of
async void
here is very bad.Describe the solution you'd like
There is an asynchronous support Initialize method, for example:
Task InitializeAsync ()
Describe alternatives you've considered
I feel almost irreplaceable
Additional context
No response