调用方法时C#Ui冻结

时间:2017-07-29 13:58:01

标签: c# function methods freeze

我有一个名为Connect()的函数,这个函数大约需要2-3秒,因为它使用了一些api请求。现在我想找到一种方法,让我的Ui不会在生病时启动这个功能。

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

我试图用线程解决它

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

和一个backgroudnworker

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

但程序仍然冻结。

   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);
            }
        }
    }

也许我只是做错了什么,希望有人可以帮助我。

2 个答案:

答案 0 :(得分:2)

使用另一个线程(无论是通过BackgroundWorker还是直接创建一个)来调用一个方法,除了在UI线程上调用某些代码然后再等待它之外,将会什么都不解决。您关心的代码仍然在UI线程中执行,阻止它。

您应该使用async / awaitTask.Run()来处理您的工作:

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);
    }
}

根据loadLoyalty()的速度而定,您可能还需要await Task.Run(loadLoyalty);,而不是直接调用它。

上面将执行它所属的UI线程中的所有代码,除了您通过Task.Run()调用的代码。

还有其他方法可以重构代码,包括与BackgroundWorker一起使用的替代方法(即只使用Control.Invoke()执行前四个语句,并在{{1方法直接)。但恕我直言,上面使用Connect() / async是今天最好的选择。

答案 1 :(得分:0)

好的,看起来很有意思。我将尝试将其转移到其他函数,因为我发现它是updateTimer冻结它。

    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));
                    }
                }
            }
        }
    }

所以我会阅读更多有关ascny的信息并等待并稍微测试一下