C#Monitor。输入SynchronizationLockException

时间:2015-06-26 17:03:26

标签: c# multithreading serial-port synchronization thread-safety

我正在开发一个C#4.5应用程序,其中许多线程需要访问相同的串行端口。

由于我也将在串口上收到回复,我想避免进一步写入,直到我收到回复并阅读它。

我有一个SerialHandler类,它是SerialPort类的包装器,write和read方法看起来像这样:

public void write(string message)
{
  Monitor.Enter(lockingObject);
  //Stuff
  serialPort.write(message);
}

public string read()
{
  //Reading procedure
  Monitor.Exit(lockingObject);
}

但是一旦我从表单发出写入,我就会得到SynchronizationLockException,说“从非同步的代码块中调用了对象同步方法”。 lockingObject是一个私有且只读的Object变量。

如何避免此错误? 非常感谢

编辑,它应该像这样工作:
线程A获得读/写权限 线程B尝试获取访问但未通过 线程A得到阅读,所以他释放了他的锁 线程B现在可以执行写入,获取锁定,读取和删除锁定

2 个答案:

答案 0 :(得分:0)

引发异常,因为不同的线程是trying to release the object

这是解决问题的简单方法:

class MySerialPort
{
    private AutoResetEvent _waithandle = new AutoResetEvent(true);
    private SerialPort _serialPort;

    public void write(string message)
    {
        _waithandle.WaitOne();
        //Stuff
        _serialPort.Write(message);
    }

    public string read()
    {
        try
        {
           ...
           ...
        }
        finally
        {
            _waithandle.Set();
        }
    }

}

第一个线程将写入,​​然后任何新的写操作将被阻塞,直到读取将释放其中一个。

修改

我在下面的评论中看到你正在寻找最快的解决方案。 根据这个link,下面的代码将在60ns(在英特尔酷睿i7 860上)完成工作,这要好得多

class MySerialPort
{
    private ManualResetEventSlim _waithandle = new ManualResetEventSlim(true);
    private SerialPort _serialPort;
    private readonly object _sync = new object();

    public void write(string message)
    {
        lock (_sync)
        {
            _waithandle.Wait();
            //Stuff
            _serialPort.Write(message);
            _waithandle.Reset();
        }

    }

    public string read()
    {
        try
        {
         ....
        }
        finally
        {
            _waithandle.Set();
        }
    }
}

答案 1 :(得分:-2)

你可以使用Mutex

class SerialHandler 
{
    private Mutex _mutex = new Mutex();
    private SerialPort _serialPort;
    public void write(string message)
    {
      _mutex.WaitOne();
      //Stuff
      _serialPort.write(message);
    }

    public string read()
    {
      //Reading procedure
      _mutex.ReleaseMutex();
    }
}

问题意味着您已尝试释放未获得的锁定。