C# Ui freezes when calling a method

我怕爱的太早我们不能终老 提交于 2020-01-05 03:37:11

问题


I got a function called Connect() this function takes about 2-3seconds because it use some api requests. Now I want to find a way that my Ui dont freeze while ill start this function.

    private void connectToolStripMenuItem_Click(object sender, EventArgs e)
    {
        Connect() // << this tooks a lot of time
    }

I have tried to solve it with a thread

    private void connectToolStripMenuItem_Click(object sender, EventArgs e)
    {
        new Thread(Connect).Start();
    }

and a backgroudnworker

    private void backgroundWorkerConnect_DoWork(object sender, DoWorkEventArgs e)
    {
        Connect();
    }

but the programm still freezes.

   private void Connect()
    {
        if (InvokeRequired)
        {
            Invoke(new MethodInvoker(Connect));
        }
        else
        {
            if (!connected)
            {
                connected = true;
                verbindenToolStripMenuItem.Enabled = false;
                trennenToolStripMenuItem.Enabled = true;
                InfoStripStatus.Text = "Status: Connected";

                irc.joinRoom(channel, BotConnectingMessage);
                chatThread = new Thread(getMessage);
                chatThread.Start();
                loadLoyalty();
                updateTimer = new System.Threading.Timer(timerViewer, null, 0, 60000);
            }
        }
    }

Maybe I'm just doing something wrong and hope someone can help me.


回答1:


Using another thread (whether via BackgroundWorker or by creating one directly) to call a method that does nothing more than to invoke some code back on the UI thread and then wait for it, is going to solve nothing. The code you care about is still executing in the UI thread, blocking it.

You should use async/await with Task.Run() to handle your work:

private async void connectToolStripMenuItem_Click(object sender, EventArgs e)
{
    await Connect();
}

private async Task Connect()
{
    if (!connected)
    {
        connected = true;
        verbindenToolStripMenuItem.Enabled = false;
        trennenToolStripMenuItem.Enabled = true;
        InfoStripStatus.Text = "Status: Connected";

        await Task.Run(() => irc.joinRoom(channel, BotConnectingMessage));
        chatThread = new Thread(getMessage);
        chatThread.Start();
        loadLoyalty();
        updateTimer = new System.Threading.Timer(timerViewer, null, 0, 60000);
    }
}

Depending on how slow loadLoyalty() is, you might also want await Task.Run(loadLoyalty); instead of just calling it directly.

The above will execute all of the code in the UI thread where it belongs, except the code you invoke via Task.Run().

There are other ways that the code could be refactored, including an alternative that works with BackgroundWorker (i.e. just using Control.Invoke() to do the first four statements, and run the rest in the Connect() method directly). But IMHO the above using async/await is the best option today.




回答2:


Okay that looks interessting. I will try to transfer it to the other functions because I found out that it is the updateTimer which freeze it.

    private void timerViewer(object state)
    {
        irc.sendChatMessage("/mods");
        UpdateStream();
        UpdateChatters();
    } 

    private void UpdateStream()
    {
        if (InvokeRequired)
        {
            Invoke(new MethodInvoker(UpdateStream));
        }
        else
        {
            StreamInformations = TwitchROClient.getStream(TwitchROClient.getIDbyUsername("xzaliax"));

            if (StreamInformations.stream != null)
            {

                viewers = StreamInformations.stream.Viewers;
                totalviews = StreamInformations.stream.channel.Views;

                if (followers == 0)
                {
                    followers = StreamInformations.stream.channel.Followers;
                }
                else
                {
                    if (followers < StreamInformations.stream.channel.Followers)
                    {
                        newFollower();
                    }
                    followers = StreamInformations.stream.channel.Followers;
                }


                InfoStripViewer.Text = "|  " + string.Format(CultureInfo.InvariantCulture, "{0:N0}", viewers).Replace(',', '.') + " :Viewer";
                InfoStripFollower.Text = "|  " + string.Format(CultureInfo.InvariantCulture, "{0:N0}", followers).Replace(',', '.') + " :Follower ";
                InfoStripTotalViewer.Text = "|  " + string.Format(CultureInfo.InvariantCulture, "{0:N0}", totalviews).Replace(',', '.') + " :Total Viewers";
                InfoStripStream.Text = "|  Stream: Online";
            }
            else
            {
                InfoStripViewer.Text = "|  -- :Viewer";
                InfoStripFollower.Text = "|  -- :Follower";
                InfoStripTotalViewer.Text = "|  -- :Total Viewers";
                InfoStripStream.Text = "|  Stream: Offline";
            }
        }
    }
    private void UpdateChatters()
    {
        if (InvokeRequired)
        {
            Invoke(new MethodInvoker(UpdateChatters));
        }
        else
        {
            ChannenlChatters = TwitchROClient.getChatters(channel);
            lbViewer.Items.Clear();

            if (ChannenlChatters != null)
            {
                if (ChannenlChatters.AllChatters != null)
                {
                    tbChat.Text += "Checking the viewer list..." + Environment.NewLine;
                    if (ChannenlChatters.AllChatters.Admins.Count >= 0) lbViewer.Items.Add("_____________Admins_____________");
                    foreach (string admin in ChannenlChatters.AllChatters.Admins)
                    {
                        lbViewer.Items.Add(String.Format("{0,5}", admin));
                    }
                    if (ChannenlChatters.AllChatters.Admins.Count >= 0) lbViewer.Items.Add("");

                    if (ChannenlChatters.AllChatters.Staff.Count >= 0) lbViewer.Items.Add("_____________Stuff______________");
                    foreach (string stuff in ChannenlChatters.AllChatters.Staff)
                    {
                        lbViewer.Items.Add(String.Format("{0,5}", stuff));
                    }
                    if (ChannenlChatters.AllChatters.Staff.Count >= 0) lbViewer.Items.Add("");

                    if (ChannenlChatters.AllChatters.GlobalMods.Count >= 0) lbViewer.Items.Add("___________Global Mods__________");
                    foreach (string globalmods in ChannenlChatters.AllChatters.GlobalMods)
                    {
                        lbViewer.Items.Add(String.Format("{0,5}", globalmods));
                    }

                    if (ChannenlChatters.AllChatters.GlobalMods.Count >= 0) lbViewer.Items.Add("");
                    foreach (string globalMods in ChannenlChatters.AllChatters.GlobalMods)
                    {
                        lbViewer.Items.Add(String.Format("{0,5}", globalMods));
                    }

                    if (ChannenlChatters.AllChatters.Moderators.Count >= 0) lbViewer.Items.Add("___________Moderators___________");
                    foreach (string moderator in ChannenlChatters.AllChatters.Moderators)
                    {
                        lbViewer.Items.Add(String.Format("{0,5}", moderator));
                    }

                    if (ChannenlChatters.AllChatters.Viewers.Count >= 0) lbViewer.Items.Add("____________Viewers_____________");
                    foreach (string viewers in ChannenlChatters.AllChatters.Viewers)
                    {
                        lbViewer.Items.Add(String.Format("{0,5}", viewers));
                    }
                }
            }
        }
    }

so i will read more about ascny and await and test it a bit



来源:https://stackoverflow.com/questions/45390080/c-sharp-ui-freezes-when-calling-a-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!