C#锁紧螺纹
我目前正在尝试阅读一些关于C中线程锁定的文章# 如果我有一个类似下面的类C#锁紧螺纹,c#,multithreading,C#,Multithreading,我目前正在尝试阅读一些关于C中线程锁定的文章# 如果我有一个类似下面的类 public class Connection { bool Connected; internal bool startConnection(Device dev) { // start connection Connected = true; } internal bool endConnection(Device dev) {
public class Connection
{
bool Connected;
internal bool startConnection(Device dev)
{
// start connection
Connected = true;
}
internal bool endConnection(Device dev)
{
// End connection
Connected = false;
}
private void readFromConnected(Device dev)
{
if(Connected)
{
// read values from connected device
}
}
}
我现在的问题是,我有多个线程使用这个类从不同的设备读取值
当一个线程在实际断开连接时尝试读取值,但由于另一个线程将连接的bool保持为true而尝试读取值时,就会出现问题
调用此类的线程如下所示
Device deviceReceived;
public PollingInstance(Device deviceSent)
{
deviceReceived = deviceSent;
aTimer = new System.Timers.Timer(2500); //1000 = 1 sec
aTimer.Elapsed += OnTimedEvent;
aTimer.Enabled = true;
}
private void OnTimedEvent(Object source, ElapsedEventArgs e)
{
for (int i = 0; i < 10; i++)
{
Connection.startConnection(deviceReceived);
Connection.readFromConnected(deviceReceived);
Connection.endConnection(deviceReceived);
}
}
很难说会发生什么,因为您发布的代码甚至不会编译 你不想这样:
private void OnTimedEvent(Object source, ElapsedEventArgs e)
{
Connection connection = whereverThisComesFrom();
if(!Monitor.TryEnter(connection)) return; // another timer is in progress
try
{
for (int i = 0; i < 10; i++)
{
connection.startConnection(deviceReceived);
connection.readFromConnected(deviceReceived);
connection.endConnection(deviceReceived);
}
}
finally
{
Monitor.Exit(connection);
}
}
private void OnTimedEvent(对象源,ElapsedEventArgs e)
{
Connection Connection=whereverThisComesFrom();
如果(!Monitor.TryEnter(connection))返回;//另一个计时器正在运行
尝试
{
对于(int i=0;i<10;i++)
{
连接。启动连接(设备接收);
连接。readFromConnected(deviceReceived);
连接。端连接(deviceReceived);
}
}
最后
{
监控。退出(连接);
}
}
很难说会发生什么,因为您发布的代码甚至无法编译
你不想这样:
private void OnTimedEvent(Object source, ElapsedEventArgs e)
{
Connection connection = whereverThisComesFrom();
if(!Monitor.TryEnter(connection)) return; // another timer is in progress
try
{
for (int i = 0; i < 10; i++)
{
connection.startConnection(deviceReceived);
connection.readFromConnected(deviceReceived);
connection.endConnection(deviceReceived);
}
}
finally
{
Monitor.Exit(connection);
}
}
private void OnTimedEvent(对象源,ElapsedEventArgs e)
{
Connection Connection=whereverThisComesFrom();
如果(!Monitor.TryEnter(connection))返回;//另一个计时器正在运行
尝试
{
对于(int i=0;i<10;i++)
{
连接。启动连接(设备接收);
连接。readFromConnected(deviceReceived);
连接。端连接(deviceReceived);
}
}
最后
{
监控。退出(连接);
}
}
你说过:
当一个线程试图在其运行时读取值时,会出现一个问题
实际上已断开连接,但仍尝试读取值,因为
另一个线程将连接的bool保持为true
您能否使用try/finally来确保正确设置布尔值
lock
关键字相当于监视器try/finally
object syncObject = new object();
Monitor.Enter(syncObject);
try {
// Code updating shared data
}
finally {
Monitor.Exit(syncObject);
}
object syncObject = new object();
lock (syncObject) {
// Code updating shared data
}
你说:
当一个线程试图在其运行时读取值时,会出现一个问题
实际上已断开连接,但仍尝试读取值,因为
另一个线程将连接的bool保持为true
您能否使用try/finally来确保正确设置布尔值
lock
关键字相当于监视器try/finally
object syncObject = new object();
Monitor.Enter(syncObject);
try {
// Code updating shared data
}
finally {
Monitor.Exit(syncObject);
}
object syncObject = new object();
lock (syncObject) {
// Code updating shared data
}
简单。为什么
连接到abool
试试这个
public class Connection
{
private int _connections = 0;
internal bool startConnection(Device dev)
{
// start connection
if(Interlocked.Increment(ref _connections) == 1)
{
//do work to connect.
}
}
internal bool endConnection(Device dev)
{
// End connection
if(Interlocked.Decrement(ref _connections) == 0)
{
//do work to disconnect.
}
}
private void readFromConnected(Device dev)
{
if(_connections > 0)
{
// read values from connected device
}
}
}
这将“工作”的一些价值观的工作。但由于异常和草率/健忘的编程,很容易导致连接处于打开状态。因此,我建议如下
Device device = ...
using(var connection = device.CreateConnection())
{
var results = connection.Read();
}
public abstract class Connection : IDisposable
{
public object Read();
}
public class Device
{
private class DeviceConnection : Connection
{
private Device Parent { get; set; }
void Dispose()
{
Parent.StopConnection();
}
public object Read()
{
return Device.readFromConnected();
}
}
private int _connections = 0;
public Connection CreateConnection()
{
// start connection
if(Interlocked.Increment(ref _connections) == 1)
{
//do work to connect.
}
return new DeviceConnection { Parent = this };
}
private bool StopConnection()
{
// End connection
if(Interlocked.Decrement(ref _connections) == 0)
{
//do work to disconnect.
}
}
private object readFromConnected()
{
//Device is guaranteed to be connected now!
}
}
简单。为什么连接到abool
试试这个
public class Connection
{
private int _connections = 0;
internal bool startConnection(Device dev)
{
// start connection
if(Interlocked.Increment(ref _connections) == 1)
{
//do work to connect.
}
}
internal bool endConnection(Device dev)
{
// End connection
if(Interlocked.Decrement(ref _connections) == 0)
{
//do work to disconnect.
}
}
private void readFromConnected(Device dev)
{
if(_connections > 0)
{
// read values from connected device
}
}
}
这将“工作”的一些价值观的工作。但由于异常和草率/健忘的编程,很容易导致连接处于打开状态。因此,我建议如下
Device device = ...
using(var connection = device.CreateConnection())
{
var results = connection.Read();
}
public abstract class Connection : IDisposable
{
public object Read();
}
public class Device
{
private class DeviceConnection : Connection
{
private Device Parent { get; set; }
void Dispose()
{
Parent.StopConnection();
}
public object Read()
{
return Device.readFromConnected();
}
}
private int _connections = 0;
public Connection CreateConnection()
{
// start connection
if(Interlocked.Increment(ref _connections) == 1)
{
//do work to connect.
}
return new DeviceConnection { Parent = this };
}
private bool StopConnection()
{
// End connection
if(Interlocked.Decrement(ref _connections) == 0)
{
//do work to disconnect.
}
}
private object readFromConnected()
{
//Device is guaranteed to be connected now!
}
}
这是否意味着您需要一个ConcurrentDictionary
来分别跟踪每个设备的连接状态?@M.kazemAkhgary这是一个输入错误。C#不会让你这么做的。是的,我想写的是如果(连接),但我的头在云端的那一刻有多个设备应该可以独立使用?介意我问一下你在建什么吗?这些设备是什么?这是否意味着您需要一个ConcurrentDictionary
来分别跟踪每个设备的连接状态?@M.kazemAkhgary这是一个输入错误。C#不会让你这么做的。是的,我想写的是如果(连接),但我的头在云端的那一刻有多个设备应该可以独立使用?介意我问一下你在建什么吗?这些设备是什么?使用TryEnter
而不只是执行锁定的目的是防止在回调仍在进行时触发计时器时发生线程泄漏。可以通过简单计数已初始化/取消初始化类的线程来解除锁定。它还将线程安全的负担放在调用代码中,最危险的地方。使用TryEnter
而不只是执行锁定的目的是防止在回调仍在进行时触发计时器时线程泄漏。可以通过简单的初始化/取消初始化类的线程计数来解除锁定。它还将线程安全的负担放在调用代码中,这是最危险的。如果在连接过程中调用另一个调用时调用了CreateConnection
,则可能最终得到一个连接,该连接认为它已连接,而实际上它并没有连接。您还假设readFromConnected
是线程安全的,如果设备实际上是一个“设备”,则可能不是这种情况。除了使用dispose模式处理这类事情外,这是一条可行之路。@Yaur的所有优点都很好。但是现在我纠正已经太晚了。我现在在床上。感谢大家的帮助,所有这些回复都给了我一个解决这个问题的想法,但需要先进行测试。如果在连接过程中调用了CreateConnection
,而另一个调用正在进行连接,那么您可能会得到一个连接,该连接认为它已连接,而实际上并没有连接。您还假设readFromConnected
是线程安全的,如果设备实际上是一个“设备”,则可能不是这种情况。除了使用dispose模式处理这类事情外,这是一条可行之路。@Yaur的所有优点都很好。但是现在我纠正已经太晚了。我现在在床上。感谢大家的帮助,所有这些回复都给了我一个解决这个问题的想法,但需要先测试。