简体   繁体   English

C#锁定线程

[英]C# Lock Threading

I am currently trying to do some reading for locking for threads in C# . 我目前正在尝试阅读一些有关C#中的线程锁定的信息。

If I have a class similar to below 如果我有一个类似于下面的课程

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

The problem I have right now is that i have multiple threads using this class to read values from different devices 我现在遇到的问题是,我有多个线程使用此类从不同设备读取值

A problem arises when a thread tries to read values when it is actually disconnected, but attempts to read the values anyways because another thread has kept the Connected bool to true; 当一个线程在实际断开连接时尝试读取值,但又试图读取值时会出现问题,因为另一个线程将Connected bool设置为true。

The thread that is calling this class looks like this. 调用此类的线程看起来像这样。

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

The part of the main class calling Polling Instance looks similar to this 主类调用轮询实例的部分看起来与此类似

foreach(Device dev in listOfDev)
{
    Task.Factory.StartNew(() => pollThread(dev));
}
private void pollThread(Device dev)
{
    PollingInstance testingPoll = new PollingInstance(dev);
}

Simple. 简单。 Why is connected a bool ? 为什么connected bool

Try this. 尝试这个。

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

This will "works" for some values of work. 这将对某些工作价值“起作用”。 But is prone to connections being left open due to exceptions and sloppy/forgetful programming. 但是由于异常和草率/健忘的编程,很容易使连接保持打开状态。 Therefore I would advise the following. 因此,我建议以下几点。

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!
    }
}

It's hard to say exactly what will happen, because the code you posted won't even compile. 很难确切说明会发生什么,因为您发布的代码甚至无法编译。

you wan't something like this: 你不会是这样的:

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

You said: 你说:

A problem arises when a thread tries to read values when it is actually disconnected, but attempts to read the values anyways because another thread has kept the Connected bool to true; 当一个线程在实际断开连接时尝试读取值,但又试图读取值时会出现问题,因为另一个线程将Connected bool设置为true。

Can you use a try/finally to ensure you set the boolean properly? 您是否可以尝试/最终确保正确设置布尔值?

The lock keyword is equivalent to a Monitor try/finally. lock关键字等效于Monitor 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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM