[英]Finishing up a thread loop after disposal
I am looking for thread safe code in C# that will avoid two issues if possible; 我正在寻找C#中的线程安全代码,如果可能的话,将避免两个问题;
The thread is calling a method which has the following while loop; 线程正在调用一个具有以下while循环的方法;
while (!Finished)
{
string request = "";
try
{
//Block until we have a message or we are terminated in dispose **
request = server.Recv(Encoding.Unicode);
//Send a response to the sender so they know we received.
server.Send(request, Encoding.Unicode);
}
catch (Exception e)
{
//Catch a termination error.
if (e.Errno == ETERM)
{
break;
}
}
syncContext.Post(
new SendOrPostCallback(delegate(object state)
{
MessageHandler handler = OnMessage;
if (handler != null)
{
handler(request);
}
}), null);
}
And the dispose currently looks like so; 处置目前看起来像这样;
public void Dispose()
{
Finished = true;
//Cause all blocking message requests and sends to terminate with exception **
FZMQConext.Dispose();
//Wait for the thread to finish up.
FThread.Join();
GC.SuppressFinalize(this);
}
Issues as I see it are; 我认为的问题是;
My event could be called even though I am disposing of my class as the thread has to finish rolling out. 我的事件可以被调用,即使我正在处理我的类,因为线程必须完成推出。 Say disposed is called between the try/catch and the syncContext.Post(). 在try / catch和syncContext.Post()之间调用dispos。 How bad is this? 这有多糟糕?
It doesn't look that bad. 它看起来并不那么糟糕。 Once you set Finished=true
. 一旦你设置Finished=true
。 it should finish posting a new delegate and then exit the loop. 它应该完成发布一个新的委托,然后退出循环。 However, you might run into CPU caching issues with Finished
. 但是,您可能会遇到Finished
CPU缓存问题。 The CPU core running the loop could read the cached value of Finished
after another thread has changed the value, so the loop could erroneously continue running. 运行循环的CPU核心可以在另一个线程更改了值后读取Finished
的缓存值,因此循环可能会错误地继续运行。 To prevent this, you should create a private field that is only modified via Interlocked
, and a method that modifies that field: 要防止这种情况,您应该创建一个仅通过Interlocked
修改的私有字段,以及一个修改该字段的方法:
private int _running = 1;
public void Stop()
{
Interlocked.Exchange(ref _running, 0);
}
and the loop would run while( _running > 0)
. 并且循环将while( _running > 0)
。
Is there any way of wrapping up this class so the user of it doesn't have to remember to call dispose. 有没有办法结束这个类,所以它的用户不必记得调用dispose。 Currently if they don't the application sits there waiting for the thread to finish, which it never will. 目前,如果他们没有应用程序坐在那里等待线程完成,它永远不会。 Setting it to a background thread seems lazy. 将它设置为后台线程似乎很懒惰。
There's really no general way to avoid putting the burden of disposing on the clients. 实际上没有一般方法可以避免将处置负担放在客户身上。 But if this class is meant to be always used by, say Winforms components, then you could write a constructor that takes a parent component and subscribe to the Disposed
event of the parent. 但是如果这个类总是被Winforms组件使用,那么你可以编写一个构造函数来获取父组件并订阅父组件的Disposed
事件。 So when the parent component (eg form) is disposed, this object gets disposed as well: 因此,当处理父组件(例如表单)时,此对象也会被处置:
public MyClass(Component parent)
{
parent.Disposed += (s,e) => this.Dispose();
}
(I'd throw out the finalizer as an option because there's no telling if/when it's going to run.) (我会把终结器作为一个选项扔出去,因为无法确定是否/什么时候会运行。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.