创建和终止集合中包含的线程
我有一个自定义集合(线程安全的 ObservableQueue)。我在集合类内部实现了业务逻辑(即将项目一项一项地出队并将它们暴露给外部)。这工作正常。为了防止集合阻塞初始化它的线程,OnservableQueue 实现了一个线程来执行该工作。现在我不能完全确定可能发生的任何陷阱。
在构造函数中初始化(不是启动!只是初始化)线程是一个坏主意吗?终止线程的最佳做法(如果不是最佳的话)是什么?请注意,我不需要知道如何终止线程,这工作得很好,我对使用一次性模式执行此操作或创建需要调用以终止线程的方法是否有问题很感兴趣。如果实现IDisposable
,关于集合/队列我需要考虑什么吗?
编辑:线程实际上只是预先初始化,以防止在入队方法中抛出NullReferenceException
,在入队方法中它会再次正确初始化(入队方法应该检查天气)出队线程已经在运行,如果不启动一个新线程)。请注意,每当所有项目都出队并且线程完成其工作时,它也将不再处于活动状态,因此每当队列为空并且添加新项目时,新线程就会开始处理队列
if (!_dequeuingThread.IsAlive)
{
// start the dequeuing thread
_dequeuingThread = new Thread(new ThreadStart(StartDequeuing));
_dequeuingThread.Name = "DeQueueThread";
_dequeuingThread.Start();
}
:语句确实需要一个初始化的线程。还有其他可能的方法可以实现此目的,但预初始化线程似乎最不麻烦。您会看到,在检查天气后,线程是否处于活动状态(在预初始化时不应如此),它会再次正确初始化。
I have a custom collection (a thread-safe ObservableQueue). I implemented the business logic inside the collection class (i.e. dequeue the items one by one and expose them to the outside). This is working fine. To prevent the collection from blocking the thread it is initialised in, the OnservableQueue implements a thread to perform that work. Now I am not perfectly sure of any pitfalls that could occur.
Is it a bad idea to initialise (not start! only initialise) the thread in the constructor? And what would be a good, if not best, practice of terminating the thread? Note, I dont need to know how to terminate a thread, that is working fine, I am rather interested in weather there is something wrong doing it using the disposable pattern or creating a method which would need to get called to terminate the thread. If implementing IDisposable
are there any things I have to take in account regarding the collection/queue?
Edit: The thread is actually only pre-initialised to prevent NullReferenceException
from being thrown in the Enqueue Method, where it is properly initilised again (the Enqueue Method is supposed to check weather a dequeuing thread is running already and if not to start a new one). Note that whenever all items are dequeued and the thread has done its work it will not be alive any longer either, so any time the queue is empty and a new item is added a new thread will get started to process the queue:
if (!_dequeuingThread.IsAlive)
{
// start the dequeuing thread
_dequeuingThread = new Thread(new ThreadStart(StartDequeuing));
_dequeuingThread.Name = "DeQueueThread";
_dequeuingThread.Start();
}
The if-statement does need an initialised thread. There are other possible ways of achieving this, but pre-initialising the thread seemed the least bothersome. You see that after checking weather the thread is alive, which it should not when being pre-initialised, it gets initialised again properly.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我没有看到在构造函数中初始化有什么问题,但显然要记住它们将在与工作线程不同的线程中初始化。
至于停止,我通常有一个易失性布尔标志,工作人员检查该标志以保持运行。如果您的工作线程完全休眠,那么让它等待一个事件而不是休眠,这样您就可以在停止它时立即唤醒它。
I don't see anything wrong with initialising in the constructor, but obviously bare in mind they will be initialised in a different thread than your worker thread.
As for stopping, I generally have a volatile boolean flag that the worker checks to keep running. If your worker thread sleeps at all, then have it wait on an event rather than sleeping, so you can wake it up immediately when stopping it.
似乎存在一个问题,即消费者将通过调用其构造函数来初始化此集合对象,并且它会认为该对象已初始化(构造函数应该执行的操作),这是不正确的,因为初始化正在发生在构造函数创建的单独线程上。因此,基本上您需要实现某种“此对象上的异步 API”来初始化此集合,以便使用者调用初始化方法(在使用构造函数创建对象之后),然后通过将回调传递给初始化方法或通过注册集合对象上的事件,消费者可以知道初始化已经完成。
There seems to be a problem with the fact that the consumer will initialize this collection object by calling its constructor and it would think that the object is initialized (that what the constructor is supposed to do), which is not correct as the initialization is happening on a separate thread created by the constructor. So, basically you need to implement some sort of "Asynchronous API on this object" to initialize this collection such that the consumer calls the initialize method (after creating the object using constructor) and then either by either passing a callback to the initialize method or by registering to an event on the collection object the consumer gets to know that the initialization has been completed.