gpt4 book ai didi

c# - 处置后完成线程循环

转载 作者:行者123 更新时间:2023-11-30 12:49:12 26 4
gpt4 key购买 nike

我正在寻找 C# 中的线程安全代码,尽可能避免两个问题;

  1. 如果线程对象在任何时候被处理掉,线程循环就会很好地退出。
  2. 当被另一个类或表单(特别是表单)使用时,使用该类的开发人员不必记住 Hook 表单的关闭事件并调用 dispose。例如。 Correct finishing of server's thread

线程正在调用一个有以下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);
}

目前的处理看起来是这样的;

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);
}

我认为是问题;

  • 我的事件可能会被调用,即使我正在处理我的类,因为线程必须完成推出。假设在 try/catch 和 syncContext.Post() 之间调用了处置。这有多糟糕?
  • 有没有什么方法可以包装这个类,这样它的用户就不必记得调用 dispose。目前,如果他们不这样做,应用程序将坐在那里等待线程完成,而这永远不会。将其设置为后台线程似乎很懒惰。

最佳答案

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(). How bad is this?

看起来没那么糟糕。一旦你设置了 Finished=true。它应该完成发布一个新的委托(delegate),然后退出循环。但是,您可能会遇到 Finished 的 CPU 缓存问题。运行循环的 CPU 核心可以读取Finished缓存 值,另一个线程更改值后,因此循环可能会错误地继续运行。为防止这种情况,您应该创建一个只能通过 Interlocked 修改的私有(private)字段,以及一个修改该字段的方法:

private int _running = 1;
public void Stop()
{
Interlocked.Exchange(ref _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. 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.

确实没有通用的方法来避免将处置的负担加在客户身上。但是,如果要始终使用此类,例如 Winforms 组件,那么您可以编写一个构造函数,它采用父组件并订阅父组件的 Disposed 事件。因此,当父组件(例如表单)被释放时,该对象也会被释放:

public MyClass(Component parent)
{
parent.Disposed += (s,e) => this.Dispose();
}

(我会放弃终结器作为一个选项,因为不知道它是否/何时会运行。)

关于c# - 处置后完成线程循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12312155/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com