我正在尝试使用一个单独的线程来处理VB.Net中的特定事件。其想法是,如果特定的事件处理程序需要一段时间才能完成,我不希望主应用程序被阻塞。如何让我的主线程循环挂起线程,同时允许它在事件发生时处理事件?
当我创建Windows窗体应用程序时,有一个UI线程处理UI事件。我不认为这个线程会不断地轮询一些变量,看看是否有人按下了按钮。我想象线程会被挂起,直到操作系统告诉它有事情要做。我试图弄清楚如何确保我的事件处理程序不会被UI线程执行。根据我所读到的内容,我可以通过从另一个线程引发事件来做到这一点。但是该线程在等待其他事件时会做什么,只是退出?
我想知道如何创建一个像UI线程一样工作的线程,只是它处理我希望它处理的事件。我不确定事件在.Net中是如何工作的。我知道事件处理程序是在引发事件的线程上运行的。我相信.Net会从一些线程池中分配线程来处理诸如计时器事件之类的事件。不过,我不清楚它是如何工作的,也不清楚这些线程在不处理事件时会做什么。
根据您的评论,我可以看到使用生产者-消费者模式可以最好地解决您想要的问题。使用这种模式,消费者线程以这样一种方式构建和启动,即它无限期地围绕一个循环旋转,等待项目出现在队列中。UI线程将使用相同的模式来实现其消息循环。以下是它的工作原理。
public class DedicatedProcessingThread
{
private BlockingCollection<object> m_Queue = new BlockingCollection<object>();
public Consumer()
{
new Thread(
() =>
{
while (true)
{
object item = m_Queue.Take(); // This blocks until an item appears.
// Do something with item here.
}
}).Start();
}
public void Post(object item)
{
m_Queue.Add(item);
}
}
魔法发生在Take
方法中。此方法旨在"挂起"(您的术语,而不是我的术语(或在队列为空时将线程状态更改为WaitSleepJoin
。一旦一个项目被排队,消耗线程就会唤醒,Take
方法返回下一个项目。这是UI线程的消息循环中使用的通用模式,除了Windows发布System.Windows.Forms.Message
值,而不是对普通的旧object
实例进行排队。您可以通过发布Delegate
实例来做类似的事情,一旦它们到达,就会在使用者线程上进行处理。
您可以让当前线程睡眠指定的毫秒数:
Threading.Thread.Sleep(100)
这将睡眠1/10秒。
但是,如果您需要在当前线程上发生排队事件,您可以使用:
Application.DoEvents()
使用DoEvents的主要问题是,您不知道实际完成了多少工作,因此它可能有些不可靠,这取决于您试图完成的任务。