.net 调用UI线程的多线程:表单数据需要锁定吗?

.net 调用UI线程的多线程:表单数据需要锁定吗?,.net,multithreading,winforms,locking,begininvoke,.net,Multithreading,Winforms,Locking,Begininvoke,我还没有问题,因为我的应用程序可以正常工作,但我想了解发生了什么,这样以后就不会有麻烦了。我主要是一名数据库/web应用程序程序员,所以线程通常不是我喜欢的东西 短版本:当多个线程更新表单数据时,UI是否需要锁定表单数据 我有一个简单的Winforms应用程序,它使用DataGridView扫描文件中的某些内容,并向用户显示结果。起初我是在UI线程中完成这一切的,但后来知道这不是一个好主意,于是决定使用ThreadPool.QueueUserWorkItem作为[ProcessorCount]项

我还没有问题,因为我的应用程序可以正常工作,但我想了解发生了什么,这样以后就不会有麻烦了。我主要是一名数据库/web应用程序程序员,所以线程通常不是我喜欢的东西

短版本:当多个线程更新表单数据时,UI是否需要锁定表单数据

我有一个简单的Winforms应用程序,它使用DataGridView扫描文件中的某些内容,并向用户显示结果。起初我是在UI线程中完成这一切的,但后来知道这不是一个好主意,于是决定使用ThreadPool.QueueUserWorkItem作为[ProcessorCount]项集合。这很好,使用委托和BeginInvoke功能在找到结果时将结果发送到UI。虽然有时结果太多,UI仍然滞后,但这是另一个问题

工作线程是完全隔离的,执行它们自己的事情。我理解多线程的概念,并且需要注意同时访问共享数据。然而,我不完全清楚的是,当不同的线程调用UI线程来更新它时会发生什么。只有UI将更新控件和表单级变量,但由于调用来自其他线程,这将如何进行?例如,如果我正在向列表中添加项或递增计数器,那么来自一个工作线程的调用是否会中断另一个工作线程?每个BeginInvoke都是它自己的调用,但是修改数据似乎仍然是一个问题

我发现的BeginInvoke示例中没有一个提到需要在UI中锁定。这两个主题是相关的,但仍然没有给出我想要的确切答案:

例如,如果我向列表中添加项目或增加计数器, 一个工作线程的调用能否中断另一个工作线程?每个人都开始觉醒 是它自己的电话,但修改数据似乎仍然是可能的 一个问题

不,一个调用不能被另一个这样的调用中断。事实上,它不能被UI线程上的任何其他操作中断。这就是为什么如果您让UI线程工作,UI本身会挂起输入并将绘制消息排队等待处理,但它们不能中断您正在进行的工作

然而,将项目添加到列表中是什么意思?或递增计数器不是UI操作。为什么要在UI线程上执行这些操作

的确,在UI线程上调用这样的操作会给您带来线程安全锁定的副作用,但这并不是真正免费的:它比在工作线程上执行简单锁定要昂贵得多

你应该考虑切换到这个方法,这也将解决你太多的更新=滞后问题:

数据变量列表、计数器以及任何由工作线程直接操作的对象。使用适当的锁定结构、方法或其他方法来提供线程安全性。 每当工作线程修改数据变量时,它也会将全局修改标志设置为true。 没有任何内容被封送到所调用的UI线程。 同时,UI线程设置一个计时器,每半秒触发一次。每当计时器触发时,UI线程都会检查modified的值并将其重置为false。您可以用它来执行此无锁操作。 如果UI线程发现数据已被修改,它将锁定所有数据变量,并根据需要重新绘制UI。 这样你最多只能得到一个昂贵的!UI会在每个计时器滴答声时更新,并且无论有多少数据来自工作线程,UI都不会延迟。另外,您可以选择定时器间隔短或长

例如,如果我向列表中添加项目或增加计数器, 一个工作线程的调用能否中断另一个工作线程?每个人都开始觉醒 是它自己的电话,但修改数据似乎仍然是可能的 一个问题

不,一个调用不能被另一个这样的调用中断。事实上,它不能被UI线程上的任何其他操作中断。这就是为什么如果您让UI线程工作,UI本身会挂起输入并将绘制消息排队等待处理,但它们不能中断您正在进行的工作

然而,将项目添加到列表中是什么意思?或递增计数器不是UI操作。为什么要在UI线程上执行这些操作

的确,在UI线程上调用这样的操作会给您带来线程安全锁定的副作用,但这并不是真正免费的:它比在工作线程上执行简单锁定要昂贵得多

你应该考虑切换到这个方法,这也将解决你太多的更新=滞后问题:

数据变量列表、计数器以及任何由工作线程直接操作的对象。使用适当的锁定结构、方法或其他方法来提供线程安全性。 每当工作线程修改数据变量时,它也会将全局修改标志设置为true。 没有任何内容被编组到UI 线程被调用。 同时,UI线程设置一个计时器,每半秒触发一次。每当计时器触发时,UI线程都会检查modified的值并将其重置为false。您可以用它来执行此无锁操作。 如果UI线程发现数据已被修改,它将锁定所有数据变量,并根据需要重新绘制UI。
这样你最多只能得到一个昂贵的!UI会在每个计时器滴答声时更新,并且无论有多少数据来自工作线程,UI都不会延迟。另外,您可以选择最短或最长的计时器间隔。

为什么您应该从一个线程执行所有UI操作:UI线程。为什么您应该从一个线程执行所有UI操作:UI线程。谢谢,听起来我应该这么做。我之所以在UI上添加列表/更改计数器,只是因为它很方便,我想我没有太多的经验例如,我需要一些特定的数据用于缓存结果的UI操作,当我从其他线程获得结果后,直接将其存储在表单中似乎是有意义的。但是工作线程可以像你建议的那样轻松地将它们存储到其他地方,以便UI检索。谢谢,听起来我应该这么做。我之所以在UI上添加列表/更改计数器,只是因为它很方便,我想我没有太多的经验例如,我需要一些特定的数据用于缓存结果的UI操作,当我从其他线程获得结果后,直接将其存储在表单中似乎是有意义的。但是工作线程可以像您建议的那样轻松地将它们存储在其他地方,以便UI检索。