[英]Threadsafe properties
我正在尝试学习C#上的线程,但是在处理属性方面有些卡住。
以我的班级NavigateIE
为例,它一次只能执行一个动作。 我以为如果我有一个物业很忙,那我就会知道实例在课外是否很忙。
class NavigateIE
{
public bool busy;
public void IEAction(string action)
{
busy = true;
var th = new Thread(() =>
{
try
{
//Do stuff
}
catch(Exception ex)
{
//report Exception
}
finally
{
busy = false;
}
});
th.SetApartmentState(ApartmentState.STA);
th.Start();
}
}
但是,由于busy = false;
仅在线程内部被调用过,然后这将不起作用,因为navigationIE.busy始终为true。
class MainElsewhere
{
private NavigateIE navigateIE = new NavigateIE();
private void Main()
{
if (!navigateIE.busy)
{
//navigateIE.busy always == true
}
}
}
我有两个问题:
1)如何设置属性,使其线程安全且busy = false;
在课外看到吗?
2)有更好的方法吗?
编辑:本质上NavigateIE是一个使用Watin处理IE的单个实例的类。 我只能在NavigateIE中调用一个方法,如果没有其他方法运行其他方法,则前一个操作尚未完成。 NavigateIE是从一个计时器滴答的主方法调用的,因此我需要检查该类是否繁忙。
navigateIE.busy == false第一次但在线程将其设置为false后,main方法仍然看到navigateIE.busy == true。
你这样做本质上是错误的。 是的, 忙碌很可能是真的,该线程将在现代多核处理器上快速开始运行。 没有实际的保证,这只是非常普遍的。 确切地说,当它变回false时也是非常不可预测的,取决于线程的作用。 包括never ,布尔不是同步原语。
我不清楚你想要实现什么,但实际上你根本不需要使用忙碌的旗帜。 IE是一个单元线程的COM对象,它已经自动将调用封送到拥有该对象的STA线程。 从另一个线程调用其Navigate()方法很好,不需要其他代码即可提供帮助。 如果您需要一个忙碌的标志来指示浏览器正在处理命令,那么您将需要在实际开始导航而不是在启动线程时将其设置为true。 也许利用此答案中的代码。
我开始写一个答案,但是这里只有很多变量。 (您应该锁定,但实际上发信号可能是更好的解决方案,等等)。 我真的认为,与其给您添加代码片段,不如将一个更好的答案指导您进行更多有关.net线程的研究。
这是一本可能对您有帮助的电子书: http : //www.albahari.com/threading/
我该如何设置属性,以便[..]
busy = false;
在课外看到吗?
您的示例无效,因为需要将busy
标记为volatile
有一个更好的方法吗?
听起来NavigateIE
所有调用总是需要序列化。 如果这是真的,我会在每个线程调用中放入一个lock
语句
public object mutex = new object(); public void IEAction(string action) { var th = new Thread(() => { lock(mutex) { //Serialzed code goes here } }); //etc. }
另外,请注意,您很少真正想要创建自己的Thread
实例-您应该使用BackgroundWorker ,从ThreadPool获取线程或使用新的Tasks并行库(TPL) 。
如果你不确定,TPL通常是最好的起点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.