我想在单个线程上“锁定”资源。我已经尝试了我能想到的每一种锁定机制,但我无法做到这一点。
在下面的示例中,当Timer触发时,我不希望DoSomething中的代码在ShowDialog返回之前执行。我希望lock语句只允许一个Form2实例返回,但这实际上都是在一个线程上运行,所以它不会阻止线程重新进入该代码块。
以下是一些示例代码,这不是我面临的确切场景,但它说明了问题。在我的实际代码中,我从连接的设备接收事件,因此没有计时器。
要重现,请创建Windows窗体应用程序并添加Form1和Form2。将此代码复制到Form1:
public partial class Form1 : Form
{
Timer _timer = new Timer();
private static object _lock = new object();
public Form1()
{
InitializeComponent();
_timer.Tick += delegate { DoSomething(); };
_timer.Interval = 5000;
_timer.Start();
}
private void DoSomething()
{
lock (_lock)
{
Form2 form2 = new Form2();
form2.ShowDialog();
}
}
}
答案 0 :(得分:4)
如果你使用ThreadStaticAttribute
,那么旗帜就可以了。
public partial class Form1 : Form
{
Timer _timer = new Timer();
[ThreadStatic]
bool inEvent = false;
public Form1()
{
InitializeComponent();
_timer.Tick += delegate { DoSomething(); };
_timer.Interval = 5000;
_timer.Start();
}
private void DoSomething()
{
// if you want to stay here and wait instead of exiting, you could do:
// while (inEvent);
if (!inEvent)
{
inEvent = true;
Form2 form2 = new Form2();
form2.ShowDialog();
inEvent = false;
}
}
}
答案 1 :(得分:1)
您无法创建表单的一个实例,将其存储在类变量中,然后使用检查其Visible属性吗?
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.visible.aspx
public partial class Form1 : Form
{
Timer _timer = new Timer();
Form2 form2 = new Form2();
public Form1()
{
InitializeComponent();
_timer.Tick += delegate { DoSomething(); };
_timer.Interval = 5000;
_timer.Start();
}
private void DoSomething()
{
if(!form2.Visible)
{
form2.ShowDialog();
}
}
}
答案 2 :(得分:1)
所以最初我认为Mutex,Semaphore,SpinWait,SpinUntil会有所帮助,但是当他们最终阻止满足您阻止输入的需要时,您的应用程序将被锁定并等待,因为您在UI线程上所以你甚至无法关闭Form2(或者你正在处理的任何东西)。
说实话,我不知道解决问题的正确方法。我认为会有一个模式或内置功能来做到这一点,但我不知道它。但是,如果你可以创建另一个可以解决问题的线程,如下面的代码所示。
public partial class Form1 : Form
{
Timer _timer = new Timer();
private readonly static object _lock = new object();
public Form1()
{
InitializeComponent();
_timer.Tick += delegate { OnTimerTick(); };
_timer.Interval = 5000;
_timer.Start();
}
private void OnTimerTick()
{
new System.Threading.Thread (DoSomething).Start();
}
private void DoSomething()
{
Console.WriteLine("Before Lock");
lock(_lock)
{
// Do stuff...
Form2 form2 = new Form2();
form2.ShowDialog();
}
Console.WriteLine("After Lock");
}
}
祝你好运。如果这有助于不要忘记投票这个答案。
谢谢, 汤姆