C# Monitor.Enter 同步锁异常
C# Monitor.Enter SynchronizationLockException
我正在开发一个 C# 4.5 应用程序,其中许多线程需要访问同一个串行端口。
因为我也会在串行端口上接收响应,所以我想避免进一步写入,直到我收到响应并阅读它。
我有一个 SerialHandler class,它是 SerialPort class 的包装器,写入和读取方法如下所示:
public void write(string message)
{
Monitor.Enter(lockingObject);
//Stuff
serialPort.write(message);
}
public string read()
{
//Reading procedure
Monitor.Exit(lockingObject);
}
但是一旦我从表单发出写入,我就会收到 SynchronizationLockException 说 "Object synchronization method was called from an unsynchronized block of code"。
lockingObject 是私有且只读的对象变量。
我怎样才能避免这个错误?
非常感谢
编辑,它应该是这样工作的:
线程 A 可以访问 read/write
线程 B 尝试获取访问权限但失败
线程 A 开始读取,所以他释放了他的锁
线程 B 现在可以执行写入、获取他的锁、读取并移除他的锁
你可以使用 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();
}
}
该问题表示您已尝试释放未获取的锁。
异常抛出是因为不同的线程是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(在 Intel Core 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();
}
}
}
我正在开发一个 C# 4.5 应用程序,其中许多线程需要访问同一个串行端口。
因为我也会在串行端口上接收响应,所以我想避免进一步写入,直到我收到响应并阅读它。
我有一个 SerialHandler class,它是 SerialPort class 的包装器,写入和读取方法如下所示:
public void write(string message)
{
Monitor.Enter(lockingObject);
//Stuff
serialPort.write(message);
}
public string read()
{
//Reading procedure
Monitor.Exit(lockingObject);
}
但是一旦我从表单发出写入,我就会收到 SynchronizationLockException 说 "Object synchronization method was called from an unsynchronized block of code"。 lockingObject 是私有且只读的对象变量。
我怎样才能避免这个错误? 非常感谢
编辑,它应该是这样工作的:
线程 A 可以访问 read/write
线程 B 尝试获取访问权限但失败
线程 A 开始读取,所以他释放了他的锁
线程 B 现在可以执行写入、获取他的锁、读取并移除他的锁
你可以使用 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();
}
}
该问题表示您已尝试释放未获取的锁。
异常抛出是因为不同的线程是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(在 Intel Core 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();
}
}
}