Home > database >  The UI freezes until the method is finished. How can not freeze?
The UI freezes until the method is finished. How can not freeze?

Time:04-21

I'm coding 'Waiting for login' in the app.

    public struct Member
    {
        public bool IsOpened, IsLogIn;
        public string Title, Name;
    }
    private static void WaitForLogin(ref Member member)
    {
        while (member.IsOpened)
        {
            if (IsLoggIn() == true)
            {
                member.Title = "Welcome to App Centrel";
                member.Name = "Omer";
                member.IsLogIn = true;
                break;
            }
            System.Threading.Thread.Sleep(1000);
        }
    }

Using the non-freezing Task, Thread, Async Etc... codes, Time problem occurs due to the ref, out in the parameter. How does the method not freeze until finished using out, ref parameter? External app is the not logged in. started freezing in my UI. I wanted to change the 'mem' variable the time when logged in in the IsLoggIn() method

CodePudding user response:

Once again, why you are using struct? Why not like this?

    public class Member
    {
        public bool IsOpened { get; set; } 
        public bool IsLogIn{ get; set; } 
        public string Title{ get; set; } 
        public string Name{ get; set; }
    }
    private static async Task WaitForLogin(Member member)
    {
        while (member.IsOpened)
        {
            if (IsLoggIn() == true)
            {
                member.Title = "Welcome to App Centrel";
                member.Name = "Omer";
                member.IsLogIn = true;
                break;
            }
            await Task.Delay(1000);
        }
    }

Then you should be able to use it like this

private async void button1_Click(object sender, EventArgs e) 
{ 
    Member asD = new Member(); 
    asD.IsOpened = true; 
    await WaitForLogin(asD); 
    MessageBox.Show("Logged In. Starting Methods"); 
}

CodePudding user response:

Thread.Sleep(1000) will suspend the current (UI) thread. This is rarely a good idea, especially on the UI thread. Also note that your example code is probably not safe. I would assume that you are modifying the IsOpened field from another thread, and this is not safe without at least marking the field as volatile. But just use a full lock if you are unsure about the level of synchronization needed.

I do not see that the ref has any real effect on the UI freezing. But I would in general recommend against mutable structs. Just use a class with properties instead.

The simplest possible workaround would be to replace the sleep with a Task.Delay and mark the method as async. This will internally be similar to starting a timer that checks for the login. But be careful with async void functions, since they can lose exception if you are not careful. Prefer to return a task for async functions, unless it has to be void, like an event-handler.

A better solution will be to let whatever component doing the login to send an event. This might be a regular event, or it might be thread-safe event, or a waithandle that may be triggered from a separate process if named. You can also use a task to signal the completion of some login process. But it is difficult to tell exactly how this should be done without more information about the internals of the system.

Regardless of the option you pick, you should probably show a modal UI dialog while waiting for login, to prevent any other interaction with the UI while waiting, while still allowing the UI to be responsive.

For example using a task to signal login and winforms for the UI

public static Task ShowDialogUntillLogin(Task loginTask){
    var myForm = new MyForm();
    loginTask.ContinueWith(t => myForm.Invoke(() => myForm.DialogResult = DialogResult.OK));
    myForm.ShowDialog();
    return loginTask;
}

This should show the form until the task is set as complete. When this happens the dialog will be closed and the method returns. Since it blocks inside the ShowDialog method UI messages will still be processed, and the UI remain responsive, but the user can only do stuff in MyForm.

  •  Tags:  
  • c#
  • Related