簡體   English   中英

C#鎖定線程

[英]C# Lock Threading

我目前正在嘗試閱讀一些有關C#中的線程鎖定的信息。

如果我有一個類似於下面的課程

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

我現在遇到的問題是,我有多個線程使用此類從不同設備讀取值

當一個線程在實際斷開連接時嘗試讀取值,但又試圖讀取值時會出現問題,因為另一個線程將Connected 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);
     }
 }

主類調用輪詢實例的部分看起來與此類似

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

簡單。 為什么connected bool

嘗試這個。

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

很難確切說明會發生什么,因為您發布的代碼甚至無法編譯。

你不會是這樣的:

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

你說:

當一個線程在實際斷開連接時嘗試讀取值,但又試圖讀取值時會出現問題,因為另一個線程將Connected bool設置為true。

您是否可以嘗試/最終確保正確設置布爾值?

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