之前可能已经以各种方式提出过这个问题,但这是我想要做的。我将有一个带有许多选项卡的Windows表单。每个选项卡都包含一个网格对象。对于用户创建的每个选项卡/网格,我希望生成一个专用线程,以便使用不断到达的信息填充该网格的内容。任何人都可以提供一个如何安全地做到这一点的例子吗?
感谢。
答案 0 :(得分:3)
在选项卡的初始化内部(假设WinForms,除非我另有说明):
Thread newThread = new Thread(() =>
{
// Get your data
dataGridView1.Invoke(new Action(() => { /* add data to the grid here */ } );
});
newThread.Start();
这显然是最简单的例子。您还可以使用ThreadPool生成线程(在服务器端应用程序中更常见)。
如果您使用的是.NET 4.0,那么您也可以使用任务并行库。
答案 1 :(得分:1)
您可以使用两种基本方法。选择在您的情况下最有意义的那个。通常没有正确或错误的选择。它们在许多情况下都能同样有效。每个都有自己的优点和缺点。奇怪的是,社区似乎经常忽略拉动方法。我不确定为什么会这样。我最近偶然发现了this一个问题,其中每个人都推荐了推送方法,尽管它是拉方法的完美情况(有一个可怜的灵魂反对牛群并且被投票并最终删除了他的答案只留下我作为唯一的反对者)。
推送方法
让工作线程将数据推送到表单。您需要使用ISynchronizeInvoke.Invoke
方法来完成此任务。这里的优点是,当每个数据项到达时,它将立即被添加到网格中。缺点是您必须使用昂贵的编组操作,如果工作线程过快地获取数据,UI可能会陷入困境。
void WorkerThread()
{
while (true)
{
object data = GetNewData();
yourForm.Invoke(
(Action)(() =>
{
// Add data to your grid here.
}));
}
}
拉动方法
让UI线程从工作线程中提取数据。您将让工作线程将新数据项排入共享队列,UI线程将定期将项目出列。这里的优点是您可以节省每个线程独立执行的工作量。队列是您的缓冲区,随着CPU使用量的减少和流量而缩小和增长。它还将工作线程的逻辑与UI线程分离。缺点是,如果您的UI线程没有足够快地轮询或保持工作线程可能会超出队列。当然,数据项不会在您的网格上实时显示。但是,如果您将System.Windows.Forms.Timer
间隔设置得足够短,可能对您来说不是问题。
private Queue<object> m_Data = new Queue<object>();
private void YourTimer_Tick(object sender, EventArgs args)
{
lock (m_Data)
{
while (m_Data.Count > 0)
{
object data = m_Data.Dequeue();
// Add data to your grid here.
}
}
}
void WorkerThread()
{
while (true)
{
object data = GetNewData();
lock (m_Data)
{
m_Data.Enqueue(data);
}
}
}
答案 2 :(得分:0)
你应该有一个线程数组,以便能够控制它们
List<Thread> tabs = new List<Thread>();
...
添加一个新的,就像:
tabs.Add( new Thread( new ThreadStart( TabRefreshHandler ) );
//Now starting:
tabs[tabs.Count - 1].Start();
最后,在TabRefreshHandler中你应该检查哪个是调用的线程号,你就会知道哪个是应该刷新的标签!