There is an application. First start. Authorization

The main window understands that there is no saved data and displays an authorization window. The main window is not even displayed yet.

After entering the login / password in the authorization form, she sends a request to the server and receives a token.

After receiving the token, the second window closes and returns control to the main one. Authorization takes place in a split second.

But after authorization to the server, you need to send a second request to receive a collection of data and subsequently transfer them to the database. All this must be done before the main form is displayed to the user.

This request has been running for 5 seconds and longer, depending on the amount of data received.

After authorization and transfer of control to the main window, it is necessary to immediately display the Splash screen to the user (a pretty window with information about progress), and execute the request in a separate thread.

When the request is completed, close the Splash screen and return control to the main one for displaying and working with it directly.

The main window cannot be displayed before receiving the data, because all of the displayed information will be taken from the information received on request. Without it, this is a bare pattern that the user does not need to see.

The problem is that I have no experience developing multi-threaded applications, so I would like to hear tips from a knowledgeable audience.

How to do this correctly?

Additional information: during the second and next program launches, it will take the authorization data from the saved properties ( Property.Settings.Default ), and the data for display in the main window will take from the local database files into which the data query results will be cached.

Afterwards, the program will, at a certain interval, launch in a separate thread a request for updating data in the local database and updating the information displayed in the window.

    1 answer 1

    Sense to do multi-threaded UI is usually no. A typical WPF application works like this: UI runs in one main stream, VM (these are objects for display and business logic) - in the same main stream, models (databases, network, calculations) - in the main and background threads.

    To begin with, you need to make sure that at the beginning of work the main window is not displayed automatically. To do this, remove StartupUri="MainWindow.xaml" from App.xaml .

    Okay, what's next? Next we need to show the windows in the code-behind. Go to App.xaml.cs and write the following:

     public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); var mainVM = new MainVM(); var mainWindow = new MainWindow() { DataContext = mainVM }; mainWindow.Show(); } } 

    This is an equivalent option that shows the main window. Now add the authorization logic.

     protected override async void OnStartup(StartupEventArgs e) { base.OnStartup(e); var mainVM = new MainVM(); Window authorizationWindow = null; if (!mainVM.HasCredentials()) // нет авторизации? { // выдаём окно var authorizationVM = new AutorizationVM(); authorizationWindow = new AutorizationWindow() { DataContext = authorizationVM }; authorizationWindow.Show(); await authorizationVM.RunAuthorization(); // в этой точке у нас есть авторизация, скармливаем её в MainVM mainVM.SetCredentials(authorizationVM); } // теперь мы авторизованы, отправляем запрос данных // окно, которое отображает Splash var dataProgressWindow = new ProgressWindow() { DataContext = mainVM }; dataProgressWindow.Show(); // когда мы открыли новое окно, можно закрыть старое authorizationWindow?.Close(); // знак вопроса нужен, а то вдруг null // дожидаемся конца загрузки данных await mainVM.DownloadData(); // тут мы готовы к работе, запускаем главное окно var mainWindow = new MainWindow() { DataContext = mainVM }; mainWindow.Show(); // а сплэш-скрин можно закрыть dataProgressWindow.Close(); // я обычно для симметрии делаю ещё // await mainVM.Run(); mainWindow.Close(); // но это не обязательно } 

    To do this, you have to separate the logic and the presentation and learn some MVVM.

    • I correctly understood that first I have to move all the fields and properties that are not related to the UI from MainWindow to the newly created class MainVM? And all the methods that you use for VM are only abstract methods for example, and not some standard ones? - MrModest
    • and also MainVM is a simple class, or to be connected to a window, should it be inherited from something? I just didn’t work with DataContext before, and here you assign an instance of the class mainVM to this field - MrModest
    • @ Mr.Modest: Exactly. This MVVM approach contributes to the separation of content from presentation. - VladD
    • @ Mr.Modest: MainVM should implement INotifyPropertyChanged . Here is an example: www.stackoverflow.com/a/573196/10105 - VladD
    • @ Mr.Modest: The WPF Binding happens to what lies in the DataContext . - VladD