我们有一个超声机器应用程序电流的实现,其中超声波对象是在UI的线程上创建的。单例实现在这里是很好的,但无论如何,不是。
最近,set方法发生了变化,它们会自动停止并重新启动超声波机,根据机器的状态,超声波机器可以花费10-100 of。在大多数情况下,这并不是很糟糕的问题,但是它仍然导致UI线程阻塞100‘s。此外,这些方法不是线程安全的,必须在初始化对象的同一线程上调用。
现在造成的最大问题是UI中没有响应的按钮,特别是滑块,它可能会在滑行时多次更新变量。因此,滑块尤其会结巴和更新非常缓慢,因为它通过数据库特性进行了许多设置调用。
什么是专门为这个超声波对象创建和工作线程的好方法,它将持续到应用程序的整个生命周期?
当前的临时解决方案包括生成一个计时器,并在我们检测到滑块没有移动200 be之后调用参数更新,然而,对于每个滑块,必须实现一个计时器,它看起来是一个非常混乱的解决方案,它解决了没有响应的滑块,但仍然偶尔阻塞UI线程。
发布于 2010-09-03 16:52:29
编程GUI的一个非常棒的地方是,您不必担心多线程会给您带来麻烦(假设您已经得到了CheckForIllegalCrossThreadCalls = true,这是您应该做的)。它都是单线程的,通过一个消息泵(队列)一个接一个地处理传入的消息。
由于您已经指出需要同步不是为了线程安全而编写的方法调用(完全可以理解),所以您没有理由不能实现您自己的消息泵来处理您的超声波对象。
一个天真、非常简单的版本可能看起来像这样(如果您在BlockingCollection 4.0上或已经安装了Rx扩展,那么.NET类是很棒的;否则,您只需要使用普通的Queue<T>并进行自己的锁定)。Warning__:这只是我刚才拼凑在一起的一个快速骨架;我没有对它的健壮性甚至正确性做出任何承诺。
class MessagePump<T>
{
// In your case you would set this to your Ultrasound object.
// You could just as easily design this class to be "object-agnostic";
// but I think that coupling an instance to a specific object makes it clearer
// what the purpose of the MessagePump<T> is.
private T _obj;
private BlockingCollection<Action<T>> _workItems;
private Thread _thread;
public MessagePump(T obj)
{
_obj = obj;
// Note: the default underlying data store for a BlockingCollection<T>
// is a FIFO ConcurrentQueue<T>, which is what we want.
_workItems = new BlockingCollection<Action<T>>();
_thread = new Thread(ProcessQueue);
_thread.IsBackground = true;
_thread.Start();
}
public void Submit(Action<T> workItem)
{
_workItems.Add(workItem);
}
private void ProcessQueue()
{
for (;;)
{
Action<T> workItem = _workItems.Take();
try
{
workItem(_obj);
}
catch
{
// Put in some exception handling mechanism so that
// this thread is always running. One idea would be to
// raise an event containing the Exception object on a
// threadpool thread. You definitely don't want to raise
// the event from THIS thread, though, since then you
// could hit ANOTHER exception, which would defeat the
// purpose of this catch block.
}
}
}
}然后会发生的事情是:每次你想以某种方式与你的超声物体互动时,你都会通过这个消息泵这样做,通过调用Submit并传递一些与你的超声对象一起工作的动作。超声对象然后同步接收发送给它的所有消息(我指的是一次一个消息),同时在它自己的非GUI线程上操作。
发布于 2010-09-03 16:34:26
您应该维护一个专用的UltraSound线程,该线程创建UltraSound对象,然后侦听来自其他线程的回调。
您应该维护委托的线程安全队列,并让UltraSound线程重复执行和删除队列中的第一个委托。
这样,UI线程可以将操作发布到队列,然后由UltraSound线程异步执行。
发布于 2010-09-03 16:52:15
我不确定我是否完全理解这个设置,但下面是我尝试的解决方案:
让滑块的事件处理程序检查上一个事件时间,并在处理用户调整之前等待50 most (只处理最近的值)如何?
然后让线程使用while循环并等待来自GUI的AutoResetEvent触发器。然后它会创建对象并设置它?
https://stackoverflow.com/questions/3637706
复制相似问题