将InvokeOnMainThread嵌套在锁内,反之亦然

时间:2014-03-31 17:26:52

标签: ios .net multithreading locking xamarin

是否将其中一个嵌入另一个中?在过去,我有一个挂起/死锁问题,我可以在执行顶部代码块时重现,当我将其更改为底部代码块时,我无法重现...我真的不明白它在时间,我还是没有。是否有关于Lock& amp;我应该知道的InvokeOnMainThread?我可以提供有关我正在做的事情的更多细节,但这更像是一个普遍问题而不是任何事情......

假设我想在后台线程中使用“DoStuff”。我有一个从多个线程访问的变量。

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

替代

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

添加信息:我的iOS应用程序具有在后台线程中运行的连接管理器功能。连接管理器功能负责保持活动和管理异步网络套接字连接。有很多实例我需要在执行操作时需要InvokeOnMainThread,否则我将收到以下错误“UIKit一致性错误:您正在调用只能从UI线程调用的UIKit方法。”

2 个答案:

答案 0 :(得分: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

现在这并不能解释为什么第二个区块会修复比赛条件,但是我的猜测是它只会改变比赛条件,你不会再次击中它(所以不要修复它,只是隐藏它)。

答案 1 :(得分: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%同步“锁定”了。