是安全的使用布尔标志从在C#停止运行一个线程 [英] Is it safe to use a boolean flag to stop a thread from running in C#

查看:191
本文介绍了是安全的使用布尔标志从在C#停止运行一个线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我主要关注的是布尔标志......是安全的使用它没有任何同步?我在几个地方看,它的原子(包括文档)。

 类MyTask
{
    私人的ManualResetEvent startSignal;
    私人CountDownLatch闩锁;
    私人布尔运行;    MyTask(CountDownLatch闩锁)
    {
        运行= FALSE;
        this.latch =锁存器;
        startSignal =新的ManualResetEvent(假);
    }    //它运行在一个线程的方法
    公共无效的run()
    {
        startSignal.WaitOne();
        而(运行)
        {
            startSignal.WaitOne();
            // ...一些code
        }
        latch.Signal();
    }    公共无效停止()
    {
        运行= FALSE;
        startSignal.Set();
    }    公共无效启动()
    {
        运行= TRUE;
        startSignal.Set();
    }    公共无效暂停()
    {
        startSignal.Reset();
    }    公共无效简历()
    {
        startSignal.Set();
    }
}

这是一种安全的方式来设计这样一个任务?任何建议,改进意见?

注:我写了我的自定义 CountDownLatch 类的情况下,你想知道我是从得到它

更新:结果
这里是我的CountDownLatch太:

 公共类CountDownLatch
{
    私人挥发性INT m_remain;
    私人的EventWaitHandle m_event;    公共CountDownLatch(诠释计数)
    {
        如果(计数℃,)
            抛出新ArgumentOutOfRangeException();
        m_remain =计数;
        m_event =新的ManualResetEvent(假);
        如果(m_remain == 0)
        {
            m_event.Set();
        }
    }    公共无效信号()
    {
        //最后一个线程还对信号设置事件。
        如果(Interlocked.Decrement(REF m_remain)== 0)
            m_event.Set();
    }    公共无效等待()
    {
        m_event.WaitOne();
    }
}


解决方案

您更好地标记它的 挥发性 虽然:


  

volatile关键字指示
  字段可能由多个被修改
  并发执行多个线程。字段
  被声明为挥发不
  受编译器的优化
  假定由单个线程访问。这个
  确保了最先进的最新值
  在野外present在任何时候。


不过,我会改变你的循环:

  startSignal.WaitOne();
    而(运行)
    {
        // ...一些code
        startSignal.WaitOne();
    }

由于它是在您的文章中一些code'当线程可能会执行的停止的(即当停止叫),这是意想不到的,甚至可能不正确。

My main concern is with the boolean flag... is it safe to use it without any synchronization? I've read in several places that it's atomic (including the documentation).

class MyTask
{
    private ManualResetEvent startSignal;
    private CountDownLatch latch;
    private bool running;

    MyTask(CountDownLatch latch)
    {
        running = false;
        this.latch = latch;
        startSignal = new ManualResetEvent(false);
    }

    // A method which runs in a thread
    public void Run()
    {
        startSignal.WaitOne();
        while(running)
        {
            startSignal.WaitOne();
            //... some code
        }
        latch.Signal();
    }

    public void Stop()
    {
        running = false;
        startSignal.Set();
    }

    public void Start()
    {
        running = true;
        startSignal.Set();
    }

    public void Pause()
    {
        startSignal.Reset();
    }

    public void Resume()
    {
        startSignal.Set();
    }
}

Is this a safe way to design a task in this way? Any suggestions, improvements, comments?

Note: I wrote my custom CountDownLatch class in case you're wondering where I'm getting it from.

Update:
Here is my CountDownLatch too:

public class CountDownLatch 
{
    private volatile int m_remain;
    private EventWaitHandle m_event;

    public CountDownLatch (int count)
    {
        if (count < 0)
            throw new ArgumentOutOfRangeException();
        m_remain = count;
        m_event = new ManualResetEvent(false);
        if (m_remain == 0)
        {
            m_event.Set();
        }
    }

    public void Signal()
    {
        // The last thread to signal also sets the event.
        if (Interlocked.Decrement(ref m_remain) == 0)
            m_event.Set();
    }

    public void Wait()
    {
        m_event.WaitOne();
    }
}

解决方案

You better mark it volatile though:

The volatile keyword indicates that a field might be modified by multiple concurrently executing threads. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times.

But I would change your loop:

    startSignal.WaitOne();
    while(running)
    {
        //... some code
        startSignal.WaitOne();
    }

As it is in your post the 'some code' might execute when the thread is stopped (ie. when Stop is called) which is unexpected and may be even incorrect.

这篇关于是安全的使用布尔标志从在C#停止运行一个线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆