调用方法时C#Ui冻结 [英] C# Ui freezes when calling a method

查看:108
本文介绍了调用方法时C#Ui冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

和一个背景工人

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

也许我只是做错了事,希望有人能帮助我.

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

推荐答案

使用另一个线程(无论是通过BackgroundWorker还是直接创建一个线程)来调用一种方法,该方法只不过是在UI线程上调用一些代码而已然后等待,什么也没解决.您关心的代码仍在UI线程中执行,从而阻止了它.

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.

您应将async/awaitTask.Run()结合使用来处理工作:

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

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

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

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

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

还有其他方法可以重构代码,包括与BackgroundWorker一起使用的替代方法(即,仅使用Control.Invoke()来执行前四个语句,然后直接在Connect()方法中运行其余的语句).但是,恕我直言,使用async/await进行上述操作是当今的最佳选择.

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.

这篇关于调用方法时C#Ui冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆