多线程暂停形成

Fre*_*red 1 c# multithreading winforms

我正在做一些MultiThreading但是表格在加载时暂停.

我试图显示表单,然后在后台它应该填充组合框而不暂停表单.

在我的Form_Load事件中,我有这个:

private void frmIni_Load(object sender, EventArgs e)
{
      Application.DoEvents();
      Thread threadOne = new Thread(GetServers);
      threadOne.Start();
}
Run Code Online (Sandbox Code Playgroud)

在我的GetServers()方法中:

private void GetServers()
{
       cboServer.BeginInvoke(
          (Action)(() => {
              servers = SmoApplication.EnumAvailableSqlServers(false);
              Thread.Sleep(1);
              foreach (DataRow server in servers.Rows)
              {
                  cboServer.Properties.Items.Add(server["Name"]);
                  Thread.Sleep(1);
              }
        }));
}
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么?表单不应该暂停,它应该工作,然后最终当线程完成时,它应该只填充组合框.

Jam*_*mes 6

是的,它阻止UI的原因很简单,因为在新线程中没有运行真正的代码.在你打电话给GetServers你的时候回到UI线程,然后做忙碌的事情(你可能根本就不用线程......).

您希望在线程中放置任何长时间运行的工作,并且只在想要更新它时回调到UI线程,例如

private void frmIni_Load(object sender, EventArgs e)
{
    Task.Factory.StartNew(() => {
        return SmoApplication.EnumAvailableServers(false);
    }).ContinueWith((task) => {
        foreach (var server in task.Result)
        {
            cboServer.Properties.Items.Add(server["Name"]);
        }
    }, TaskScheduler.FromCurrentSynchronizationContext());
}
Run Code Online (Sandbox Code Playgroud)

注意事项

  • DoEvents尝试多线程时不要使用,特别是当您不了解它的用法时.
  • 除非您确定需要(例如,长时间运行的I/O任务),否则不要启动新线程
  • 不要Thread.Sleep用来模拟"暂停"(你似乎在做)
  • 使用线程池进行短期工作(像这样).