EDIT2 - > 看看底部; < - EDIT2c#lock()掛在第二次鎖定嘗試
我遇到了奇怪的(對我來說,至少)行爲。
我甚至創建了簡單的WinForms類和簡單的類(下面的代碼)來測試它。
我一直認爲打電話lock(m_lock)
如果以前的lock(m_lock)
通話沒有結束,第一個會等待並進入第二個鎖定範圍。不。
的動作流程是:
創建
Class1
對象;調用
Start()
方法;調用
DoSomething()
方法,而m_lock
被鎖定在run
方法;
輸出是:
起動()
試圖獲取鎖
獲得的鎖
發行鎖
試圖獲取鎖
獲得的鎖
DoSomething的()試圖獲取鎖
... ...掛起
我缺少什麼或者做錯了嗎?我是C#的新成員(來自C++),因此在C#中可能有一些陷阱。
它仍然掛...(由時間我最後寫這篇文章)
編輯 - > 在現實世界中我用鎖來保護讀/寫/配置上的SerialPort(帶同步讀/寫,而不是異步)。我在dbg中看到有一些內部的WaitOne
調用。不知道它是否相關。 < --edit
這裏的例子:
using System;
namespace LockTester
{
public class Class1
{
object m_lock = null;
bool m_isRunning;
System.Threading.Thread m_thread = null;
public Class1()
{
Console.WriteLine("Class1 ctor");
m_lock = new object();
m_isRunning = false;
}
public void DoSomething(){
Console.WriteLine("DoSomething() Trying to acquire lock");
lock(m_lock){
Console.WriteLine("DoSomething() Acquired lock");
}
Console.WriteLine("DoSomething() Released lock");
}
public void Start(){
Console.WriteLine("start()");
m_isRunning = true;
if (m_thread == null){
m_thread = new System.Threading.Thread(Run);
}
m_thread.Start();
}
public void Stop(){
Console.WriteLine("stop()");
m_isRunning = false;
}
private void Run(){
while (m_isRunning){
Console.WriteLine("Trying to acquire lock");
lock(m_lock){
Console.WriteLine("Acquired lock");
System.Threading.Thread.Sleep(1000);
}
Console.WriteLine("Released lock");
System.Threading.Thread.Sleep(1000);
}
}
}
}
EDIT2:
好了,找到了答案。這是一個更常見的分母。我已經找到了一個解決方案將控制檯輸出重定向到TextBox(純粹爲了測試的原因,你知道 - 小測試應用程序可以捕獲測試對象的內部消息被打印到控制檯)。
下面的代碼:我在窗體的構造函數中使用
:
_writer = new TextBoxStreamWriter(textBox1, this);
Console.SetOut(_writer);
public class TextBoxStreamWriter : TextWriter
{
TextBox _output = null;
Form _form = null;
object _lock = new object();
delegate void SetTextCallback(string text);
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (_output.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
_form.Invoke(d, new object[] { text });
}
else
{
_output.AppendText(text);
}
}
public TextBoxStreamWriter(TextBox output, Form form)
{
_output = output;
_form = form;
}
public override void Write(char value)
{
lock (_lock)
{
base.Write(value);
SetText(value.ToString());
}
}
public override Encoding Encoding
{
get { return System.Text.Encoding.UTF8; }
}
}
任何人都可以解釋我爲什麼這引起了這個問題?
根據您的編輯,似乎您的一個鎖定塊內的串行I/O代碼被阻止。爲什麼它停滯不前,很難猜測沒有看到實際的代碼... – elgonzo
這段代碼對我來說是完美的。 –
@SimonWhitehead - 它是平臺/配置特定的嗎?我使用4.0CP的Target Framework運行它,但「真正的」運行到3.5 ...這裏的平分母是我的機器。 – jaor