繁体   English   中英

线程安全属性

[英]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/

  1. 我该如何设置属性,以便[..] busy = false; 在课外看到吗?

    您的示例无效,因为需要将busy标记为volatile

  2. 有一个更好的方法吗?

    听起来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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM