C#:等待变量变为非空
.Net 奇怪的锁定语义再次困扰着我。
我正在启动一个线程,子线程依次启动一个表单。 父线程应该等待,直到创建表单。
我的第一次尝试是使用监视器来监视 Form 变量:
private void OpenForm()
{
if (FormThread == null)
{
Monitor.Enter(Form);
FormThread = new Thread(FormStub);
FormThread.SetApartmentState(ApartmentState.STA);
FormThread.Start();
Monitor.Wait(Form);
Monitor.Exit(Form);
}
}
private void FormStub()
{
Form = new ConnectorForm();
Monitor.Enter(Form);
Monitor.PulseAll(Form);
Monitor.Exit(Form);
Application.Run(Form);
}
...这会引发异常。 Monitor.Enter() 失败,因为 Form == null。
我可以很容易地创建一个虚拟整数或其他东西(我实际上认为我可以使用 FormThread 变量),但我想知道是否有更优雅的解决方案。
.Net's odd locking semantics are bugging me again.
I'm launching a thread, the child thread in turns starts a form. The parent thread should wait until the form is created.
My first attempt was to use a Monitor to watch the Form variable:
private void OpenForm()
{
if (FormThread == null)
{
Monitor.Enter(Form);
FormThread = new Thread(FormStub);
FormThread.SetApartmentState(ApartmentState.STA);
FormThread.Start();
Monitor.Wait(Form);
Monitor.Exit(Form);
}
}
private void FormStub()
{
Form = new ConnectorForm();
Monitor.Enter(Form);
Monitor.PulseAll(Form);
Monitor.Exit(Form);
Application.Run(Form);
}
... This throws an exception. Monitor.Enter() fails, since Form == null.
I could very easily create a dummy integer or something (I actually think I'll canabalize the FormThread variable), but I was wondering if there was a more elegant solution.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
对于这种情况,更好的同步原语:
Better synchronisation primitive for this case:
在当前线程上执行旋转等待是否会删除使用单独线程来启动新表单的全部意义? 除非我误解了什么,否则您只想同步创建新表单。 (有什么理由需要将其驻留在不同的 STA 中吗?)
Doesn't performing a spin-wait on the current thread delete the whole point of using a separate thread to lanch the new form? Unless I'm misunderstanding something, you just want to create the new form synchronously. (Is there any reason it needs to reside in a different STA?)
您可以尝试以下方法,它使用单个
object
/Monitor
作为消息机制:原始线程持有锁,直到它调用
Monitor.Wait
>; 这让第二个线程(已经启动)创建表单,使原始线程恢复活力,然后释放; 只有在Form
存在后,原始线程才会退出。You could try the following, which uses a single
object
/Monitor
as the message mechanism:The original thread holds the lock until it calls
Monitor.Wait
; this lets the second thread (already started) in to create the form, pulse the original thread back into life, and release; the original thread then exits only afterForm
exists.对于类似的情况,我倾向于使用 AutoResetEvent这些:
I tend to use the AutoResetEvent for cases like these:
传递 EventWaitHandle 的另一种方法是将其作为参数传递给 FormStub(这样就不会弄乱您的对象模型):
Another way to pass an EventWaitHandle is to pass it to FormStub as a parameter (so it does not clutter your object model):
使用静态布尔值来标记表单是否已加载。
它是原子的,因此不需要锁定。
在主代码中只需执行类似的操作,
真正的问题是你为什么要这样做?
通常您希望主线程运行 GUI 内容,而辅助线程运行帮助程序代码。
如果您解释为什么需要它,我们也许可以想出更好的技术。
Use a static bool to flag whether or not the Form has loaded.
It is atomic so won't need locking.
In the main code just do something like
The real question is why are you doing this?
Usually you want the main thread to run GUI stuff, and secondary threads to run helper code.
If you explain why you need it we can maybe come up with a better technique.