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)
任何人都知道我能做些什么才能实现这一目标?
好吧,您可以使用Invoke将委托编组回到ListBox可以安全访问的UI线程.
public void loop()
{
form1.Invoke(new Action(
() =>
{
form1.addConsoleMessage("test");
}));
}
Run Code Online (Sandbox Code Playgroud)
但是,唉,这种选择是次等的.实际上,这些编组技术通常很糟糕.别弄错我的意思.Invoke(和类似的)有时间和地点,但是,像许多情况一样,这不是其中之一.
Invoke在整个地方撒上电话.BeginInvoke).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线程可以消耗什么.它通常不是一个问题,但有一些技术可以解决这个问题.