死锁引起的线程问题(线程新手) [英] Threading problem with deadlock (New to threading)
问题描述
你好!
我想我再次需要您的帮助.这次是关于线程的.
我的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 theMonitor
class.
System.Threading.Monitor
UsingInvoke
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屋!