2017-07-29 29 views
0

我得到一个名为Connect()的函数,因为它使用了一些API请求,所以这个函数需要大约2-3秒。现在我想找到一种方式,当我开始使用这个功能时,我的Ui不会冻结。C#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(); 
    } 

但仍PROGRAMM冻结来解决它。

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

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

+0

开始一个新的线程不应该冻结UI,因为它有它自己的线程 –

+0

而'连接();'方法不依赖或调用UI线程上的任何东西?如果你用'System.Threading.Thread.Sleep(3000)'替换'Connect()'中的任何东西;'它是否仍然冻结UI? (用最后两个选项对它进行测试) – rene

+0

好吧,我试着用Connect()内容替换睡眠(3000),现在没有更多的冻结。但我不明白为什么,因为在连接()函数是没有什么需要那么久。我在顶部添加Connect()的内容:) –

回答

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()首先要做的四项声明,并直接运行在Connect()方法的其余部分)的替代品。但恕我直言,上述使用async/await是今天的最佳选择。

+0

Thx队友后读了一下asyn/await和任务它只适用于几个变化 –

0

好的,看起来interssting。我会尝试将它传递给其他函数,因为我发现它是冻结它的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并等待和测试有点

+0

你的计时器回调做同样的事情你的点击处理程序。它在UI线程上运行_everything_。当然,这会阻止UI线程在工作。如果没有可靠地再现问题的好的[mcve],就不可能提供任何具体的建议,但基本解决方案仍然是一样的:不要阻塞UI线程以进行长时间运行。你似乎在做I/O,所以可能已经有异步方法可以调用。如果没有,你可以在'await Task.Run()'成语上回退,就像我在这里发布的答案一样。 –

相关问题