2014-03-31 25 views
2

将其中一个嵌套在其他内部吗?在过去,我有一个挂起/死锁问题,我可以在做代码的顶层代码块时重现,当我将其更改为底部代码块时,我无法重现......我真的不明白它在时间,而我仍然没有。我应该知道关于锁的& InvokeOnMainThread的组合吗?我公司可提供约我在做什么更多的细节,但是这是比任何事情的一般问题...在锁内嵌套InvokeOnMainThread,或者反之亦然

比方说,我想“DoStuff”在后台线程。我有一个从多个线程访问的变量。

lock(stuff) 
{ 
    InvokeOnMainThread (delegate { 
     stuff.DoStuff(); 
    }); 
} 

备用

InvokeOnMainThread (delegate { 
    lock(stuff) 
    { 
     stuff.DoStuff(); 
    } 
}); 

新增信息:我有在后台线程运行的连接管理器功能,iOS应用程序。连接管理器功能负责保持活动并管理异步网络套接字连接。有很多情况下,我需要InvokeOnMainThread当做事情,否则我会得到以下错误“UIKit一致性错误:您正在调用UIKit方法,只能从UI线程调用。”

+0

,如果你在后台线程想DoStuff(),为什么你运行它在主线程上? – Jason

+0

我试图简化一个潜在的复杂问题......也许这使得这个问题变得无法回答。看到上面添加的内容 – LampShade

回答

1

两者之间的区别是,代码第二块不会阻止任何来自您DoStuff之前执行的线程上执行。

实施例:

lock (stuff) { 
    InvokeOnMainThread (delegate { Console.WriteLine ("a"); } } 
} 
Console.WriteLine ("b"); 

将打印:

a 
b 

而此代码:

InvokeOnMainThread (delegate { 
    lock (stuff) { 
     Console.WriteLine ("a"); 
    } 
} 
Console.WriteLine ("b"); 

通常会(但不一定)打印:

b 
a 

现在,这并不能解释为什么第二块会操纵比赛的条件,但我的猜测是,它只是改变了比赛的条件足以让你不再打它(所以不是修复它,只是隐藏) 。

0

因此,如果我们假设这是只有在你使用的锁(的东西),唯一合乎逻辑的解释方法为什么是第一种情况导致你僵局线程A(背景THEAD)谈到这个方法里面去锁(东东) 。所以现在东西被锁定在线程A上。现在线程A调用MainThread,如果你从stuff.DoStuff()调用这个方法,你会得到死锁,因为MainThread会运行到锁(东西),它会等到线程A释放锁),但当MainThread调用完成时,线程A将释放......导致死锁。

即使你没有从stuff.DoStuff()从MainThread的任何地方调用此方法发生死锁,也有第一种情况发生的可能性唯一的区别是InvokeOnMainThread不执行stuff.DoStuff()但它只是排队在MainThread上执行导致相同的死锁情况。

现在第二个例子中,lock(stuff)在InvokeOnMainThread中,所以不会发生死锁,因为lock(stuff)只是在MainThread上做的,所以它没有任何功能,所以你可以删除它。因为在MainThread上执行代码已经100%同步“锁定”了。

相关问题