死锁引起的线程问题(线程新手) [英] Threading problem with deadlock (New to threading)

查看:55
本文介绍了死锁引起的线程问题(线程新手)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好!
我想我再次需要您的帮助.这次是关于线程的.
我的GUI启动了我的子线程.而且线程启动没有问题* yay *
但是当我想调用"Stop"或"GoOn"时,会出现类似死锁的情况.
这是我在线程中运行的代码:

 公共  class  MixUpdater
{
    私有 易失性 布尔 MixUpdaterShouldStop = 错误;
    公共 布尔 MixUpdaterStopped { get ; 私有 设置; }
     volatile  对象 locker =  对象();
    私有 布尔 MixerUpdaterGoOn =  false ;

    公共 无效 UpdateMixes(对象 o)
    {

        // 变量声明等.

         for ( int  i =  1 ; i <  = max; i ++)
        {
            resp = threeTracksConnection.GetMixes(,类型, 25 ,sortType,i);

            Debug.WriteLine("  + Thread.CurrentThread.ManagedThreadId)";

            如果(i ==  1 )
                max = resp.TotalPages;
            其他
            {
                同时(!MixerUpdaterGoOn)
                {
                    如果(MixUpdaterShouldStop)
                         break ;
                    Thread.Sleep( 10 );
                }
            }

             foreach (在
            {
                dispatcher.Invoke((Action)(()= >  {Mixes.Add(m);}), null );
            }

            MixerUpdaterGoOn =  false ;
        }

        MixUpdaterStopped =  true ;

    }

    公共 无效 RequestStop()
    {
        MixUpdaterShouldStop =  true ;
    }

    公共 无效 LoadMore()
    {
        MixerUpdaterGoOn =  true ;
    }
}



要停止它(至少我尝试过),我使用以下代码:

 如果(MixListUpdaterThread!= )
{
  MixListUpdater.RequestStop();
   while (!MixListUpdater.MixUpdaterStopped)
    Thread.Sleep( 10 );
} 



同样,"LoadMore"-方法不起作用.

我认为这是由于"Thread.Sleep"引起的,但我无法弄清楚.
我也不知道我是否应该使用lock()以及在哪里使用.

我希望你能帮助我.

谢谢,Markus

解决方案

您可能应该看看Monitor类.
System.Threading.Monitor

使用Invoke执行线程同步,我通常只使用它来允许后台线程更新UI元素.

当我在后台有多个线程访问对象时,通常使用与此类似的代码示例:

 公共  class  MixCollection()
{

  公共 代理  void  MixAdded(混合混合) ;
  公共 事件 MixAdded OnMixAdded;

  私有列表< Mix> _theList =  List< Mix>();

  公共 无效添加(混合项)
  {
    布尔 complete =  false ;
    同时(!完成)
    {
      如果(System.Threading.Monitor.TryEnter(_theList, 100 ))
      {
        尝试
        {
          complete =  true ;
          _theList.Add(item);
          如果(OnMixAdded!= )
            OnMixAdded(item);
        }
        最终
        {
          System.Threading.Monitor.Exit(_theList);
        }
      }
      其他
        System.Threading.Thread.Sleep( 100 );
    }
  }

}

公共  MixUpdater()
{

  私有线程_bgThread;
  私有 MixCollection _mixes;

  公共 MixUpdater(MixCollection混合)
  {
    _mixes =混合;
    开始();
  }

  私有 布尔 _stop =  false ;

  公共 无效 Stop(){_stop =  true ; }
  公共 无效 Start()
  {
    如果(_ stop)
    {
      _bgThread =  Thread( ThreadStart(Work));
      _bgThread.Start();
    }
  }

  私有 无效 Work()
  {
    同时(!_ stop)
    {
      // 在此处进行混合检查,添加新项目,然后执行以下操作,以得到新的混合
      _mixes.Add(mix);
      
      Thread.Sleep( 1000 );
    }
  }

} 



然后在您的用户界面中:

请注意,尽管回到了UI类中,但使事件冒泡的线程仍然是后台线程,因此您需要调用以更新UI.

 公共  class  MyForm:表单
{

  MixCollection _mixes;
  MixUpdater _mixUpdater;

  公共 MyForm()
  {
    _mixes =  MixCollection();
    _mixes.OnMixAdded + =  MixCollection.MixAdd(OnMixAdded);
    _mixUpdater =  MixUpdater(_mixes);
  }

  公共 无效 OnMixAdded(混合混合)
  {
    ListBox.dispatcher.Invoke((Action)(()= >  {ListBox.Items.Add(mix);}),
Here is my code running in the thread:

public class MixUpdater
{
    private volatile bool MixUpdaterShouldStop = false;
    public bool MixUpdaterStopped { get; private set; }
    volatile object locker = new object( );
    private bool MixerUpdaterGoOn = false;

    public void UpdateMixes(object o)
    {

        //varible declaration etc.

        for ( int i = 1; i <= max; i++ )
        {
            resp = eightTracksConnection.GetMixes(null, genres, 25, sortType, i);

            Debug.WriteLine("Baby says " + Thread.CurrentThread.ManagedThreadId);

            if ( i == 1 )
                max = resp.TotalPages;
            else
            {
                while ( !MixerUpdaterGoOn )
                {
                    if ( MixUpdaterShouldStop )
                        break;
                    Thread.Sleep(10);
                }
            }

            foreach ( Mix m in resp.Mixes )
            {
                dispatcher.Invoke((Action)( ( ) => { Mixes.Add(m); } ), null);
            }

            MixerUpdaterGoOn = false;
        }

        MixUpdaterStopped = true;

    }

    public void RequestStop( )
    {
        MixUpdaterShouldStop = true;
    }

    public void LoadMore( )
    {
        MixerUpdaterGoOn = true;
    }
}



To stop it (at least I try) I use the following code:

if ( MixListUpdaterThread != null )
{
  MixListUpdater.RequestStop( );
  while ( !MixListUpdater.MixUpdaterStopped )
    Thread.Sleep(10);
}



Also the "LoadMore"-Method doesn''t work.

I think it is because of the "Thread.Sleep"s, but I cant figure it out.
I also don''t know if I should use lock() and where.

I hope you can help me.

Thanks, Markus

解决方案

You should probably take a look at the Monitor class.

System.Threading.Monitor

Using Invoke performs a thread synchronisation and I normally only use it to allow background threads to update UI elements.

I normally use a code sample similar to this when I have multiple threads access objects in the background:

public class MixCollection()
{

  public delegate void MixAdded(Mix mix);
  public event MixAdded OnMixAdded;

  private List<Mix> _theList = new List<Mix>();

  public void Add(Mix item)
  {
    bool complete = false;
    while(!complete)
    {
      if(System.Threading.Monitor.TryEnter(_theList, 100))
      {
        try
        {
          complete = true;
          _theList.Add(item);
          if(OnMixAdded != null)
            OnMixAdded(item);
        }
        finally
        {
          System.Threading.Monitor.Exit(_theList);
        }
      }
      else
        System.Threading.Thread.Sleep(100);
    }
  }

}

public class MixUpdater()
{

  private Thread _bgThread;
  private MixCollection _mixes;

  public MixUpdater(MixCollection mixes)
  {
    _mixes = mixes;
    Start();
  }

  private bool _stop = false;

  public void Stop() { _stop = true; }
  public void Start()
  {
    if(_stop)
    {
      _bgThread = new Thread(new ThreadStart(Work));
      _bgThread.Start();
    }
  }

  private void Work()
  {
    while(!_stop)
    {
      //do your mix check here adding new items doing the following where you get a new mix
      _mixes.Add(mix);
      
      Thread.Sleep(1000);
    }
  }

}



Then in your UI:

Note although back in your UI class, the thread bubbling the event is still a background thread and as such you need to invoke to update your UI.

public class MyForm : Form
{

  MixCollection _mixes;
  MixUpdater _mixUpdater;

  public MyForm()
  {
    _mixes = new MixCollection();
    _mixes.OnMixAdded += new MixCollection.MixAdd(OnMixAdded);
    _mixUpdater = new MixUpdater(_mixes);
  }

  public void OnMixAdded(Mix mix)
  {
    ListBox.dispatcher.Invoke((Action)( ( ) => { ListBox.Items.Add(mix); } ), null);
  }

}



I''ve typed all this off the top of my head, so I''m sorry if it''s not quite right in your project, but you should get the general idea.


这篇关于死锁引起的线程问题(线程新手)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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