Xamarin.Mac NSThread.Start()堆栈溢出

时间:2014-04-04 01:46:32

标签: c# macos mono xamarin

我有一个相当复杂的Xamarin.Mac应用程序。事实上,它是一个Windows窗体应用程序,但我们使用Mono for Mac与本机Mac GUI兼容。我们的业务逻辑组件之一涉及使用FSWatcher监视文件系统的更改。不幸的是,Mac上的FSWatcher严重受损,让我们通过Xamarin.Mac使用本机FSEvents API。

在业务逻辑的深处,我有一个名为CBFileSystemWatcher的自定义类,它包装.NET FSWatcher,并且在mac上提供了FSWatcher期望的业务逻辑和mac上的FSEvents之间的适配器。在这个兼容性类中,我有

private FSEventStream eventStream;
//...
this.eventStream.ScheduleWithRunLoop (NSRunLoop.Main);

调度主运行循环上的文件系统事件。不幸的是,这意味着GUI会阻止FS事件处理,因此如果打开模态对话框,突然之间,例如,fs事件将停止处理。

我的想法是为FS事件调度创建一个新的runloop,我看起来像

NSThread.Start(()=>{
    // Some other code
    this.eventStream.ScheduleWithRunLoop (NSRunLoop.Current);
});

障碍,我认为,这个代码可能在另外两个线程启动层内运行。出于测试目的,我有以下代码,我需要上面的代码:

NSThread.Start(()=>{
    int i = 0;
});

在中间线上有一个断点,以确定它是否被击中。 10次​​中有9次我得到以下堆栈溢出:

Stack overflow in unmanaged: IP: 0x261ba35, fault addr: 0xb02174d0
Stack overflow in unmanaged: IP: 0x261ba35, fault addr: 0xb02174d0

(地址发生变化,但经常重复) 十分之一的代码与预期完全一致,我在i = 0

上休息

为了进一步测试,我将上述测试放在我的主AppDelegate.cs FinishedLaunching方法中。在那里,代码可靠地工作。

为了进一步混淆问题,我在FinishedLaunching

的开头放置了以下代码
var fooThread = new Thread(() =>
{
    var barThread = new Thread(()=>{
        NSThread.Start(() =>
        {
            int i = 4;
        });
    });
    barThread.Start();
});
fooThread.Start();

对于fooThread.Start();barThread.Start();int i = 4;上的断点,代码的工作方式完全符合预期,其中的点按相反顺序命中。

我的问题是,有没有人对如何开始取消这个有任何想法? SO是如此突然,我甚至不知道从哪里开始。

1 个答案:

答案 0 :(得分:1)