Windows窗体,循环和线程

Pio*_*cki 1 c# multithreading winforms

我想制作服务器应用程序.在开始时,它应该创建用于组织每个连接的线程并在Listbox中写入日志.我有问题因为我不知道在哪里可以创建可以访问Form1.Listbox1的新线程.这是我试过的:

public class ServerLoop
{
    Form1 form1;
    public ServerLoop(Form1 f)
    {
        form1 = f;
    }
    public void loop()
    {
        form1.addConsoleMessage("test");
    }
}
Run Code Online (Sandbox Code Playgroud)

和Form1类:

public partial class Form1 : Form
{
    public Thread tServerLoop;
    public ServerLoop serverLoop;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        console.Items.Clear();
        players.Items.Clear();
        players.Items.Add("Witaj w serwerze");
        addConsoleMessage("test");
        serverLoop = new ServerLoop(this);
        tServerLoop = new Thread(serverLoop.loop);
        tServerLoop.Start();
    }

    private void connectButton_Click(object sender, EventArgs e)
    {

    }

    public void addConsoleMessage(String msg)
    {
        console.Items.Add(msg);
    }
}
Run Code Online (Sandbox Code Playgroud)

任何人都知道我能做些什么才能实现这一目标?

Bri*_*eon 5

好吧,您可以使用Invoke将委托编组回到ListBox可以安全访问的UI线程.

public void loop() 
{
  form1.Invoke(new Action(
    () =>
    {
      form1.addConsoleMessage("test");
    }));
} 
Run Code Online (Sandbox Code Playgroud)

但是,唉,这种选择是次等的.实际上,这些编组技术通常很糟糕.别弄错我的意思.Invoke(和类似的)有时间和地点,但是,像许多情况一样,这不是其中之一.

  • 代码很难看,因为你必须Invoke在整个地方撒上电话.
  • 它迫使您进入UI线程和工作线程紧密耦合的设计.
  • 工作线程正在规定UI的更新频率.
  • 效率低下.
  • 它可以泛滥UI消息队列(至少它可以BeginInvoke).
  • 工作线程必须等待来自UI线程的响应才能继续(Invoke无论如何都会如此).

那么我该如何解决这个问题呢?嗯,当然,无聊的旧System.Windows.Forms.Timer和新奇ConcurrentQueue<T>.

public partial class Form1 : Form                    
{
  private ConcurrentQueue<string> queue = new ConcurrentQueue<string>();

  public Form1()                    
  {                    
    InitializeComponent();                    
  }                    

  private void Form1_Load(object sender, EventArgs e)                    
  {                    
    console.Items.Clear();                    
    console.Items.Add("test");
    players.Items.Clear();                    
    players.Items.Add("Witaj w serwerze");                    
    Task.Factory.StartNew(
      () =>
      {
        while (GetSomeCondition())
        {
          string value = GetSomeValue();
          queue.Enqueue(value);
        }
      });
  }                    

  private void YourTimer_Tick(object sender, EventArgs e)                    
  {                    
    string value;
    while (queue.TryDequeue(out value)
    {
      console.Items.Add(value);
    }
  }                                        
}                    
Run Code Online (Sandbox Code Playgroud)

那我们现在有什么.

  • 它看起来很优雅.
  • 我们的后台任务只知道队列.紧耦合已被打破.
  • UI线程现在正在规定更新频率......它的应用方式.
  • 效率更高.
  • UI消息队列不可能被泛洪.
  • 最后,工作人员可以快速地完全不知道UI线程正在做什么.

然而,该解决方案并非完全没有缺点.既然我们的工作线程正在加速,那么它可能会为队列产生更多项目,然后UI线程可以消耗什么.它通常不是一个问题,但有一些技术可以解决这个问题.