You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不阻塞的情况下等待触发事件的长时间运行任务?

问题分析与解决方案

你的事件处理程序未被调用,核心原因是:CLLocationManager的事件分发依赖线程的运行循环(RunLoop),而你用WaitHandle.WaitOne()直接阻塞了线程,导致RunLoop无法运转,系统无法将事件传递给处理方法。

解决方案一:保持线程RunLoop活跃(非异步方式)

修改Scanner方法,避免直接阻塞线程,通过循环等待取消令牌的同时,让RunLoop持续处理事件:

private void Scanner()
{
    this.scanner = new CLLocationManager();
    this.scanner.DidRangeBeacons += HandleDidRangeBeacons;
    // 补充定位权限请求、扫描区域设置等初始化逻辑
    ...

    try
    {
        // 循环等待取消,每次等待100ms后触发一次RunLoop事件处理
        while (!this.scannerCancellationTokenSource.Token.WaitHandle.WaitOne(100))
        {
            // 让当前线程的RunLoop处理待办事件,确保回调能被触发
            NSRunLoop.Current.RunUntil(NSDate.FromTimeIntervalSinceNow(0.1));
        }
    }
    catch(OperationCanceledException) { }
    finally
    {
        // 清理资源,避免内存泄漏
        this.scanner.DidRangeBeacons -= HandleDidRangeBeacons;
        this.scanner.StopRangingBeacons(null);
        this.scanner.Dispose();
    }
}

解决方案二:用async/await(更优雅,且不会阻塞启动线程)

你对async/await的理解有误:async/await不会阻塞启动和停止的调用线程,它的设计初衷就是避免阻塞。改造后的代码如下:

// 启动时直接调用异步方法,立即返回Task,不会阻塞调用线程
this.scannerTask = ScannerAsync();

private async Task ScannerAsync()
{
    this.scanner = new CLLocationManager();
    this.scanner.DidRangeBeacons += HandleDidRangeBeacons;
    // 补充初始化逻辑
    ...

    try
    {
        // 用Task.Delay配合取消令牌等待,不会阻塞线程,RunLoop正常运转
        await Task.Delay(Timeout.Infinite, this.scannerCancellationTokenSource.Token);
    }
    catch(OperationCanceledException) { }
    finally
    {
        // 清理资源
        this.scanner.DidRangeBeacons -= HandleDidRangeBeacons;
        this.scanner.StopRangingBeacons(null);
        this.scanner.Dispose();
    }
}

public void StopScanner()
{
    this.scannerCancellationTokenSource.Cancel();
}

调用ScannerAsync()时,方法会立即返回Task对象,启动线程无需等待扫描逻辑执行完成,完全满足你“不阻塞启动/停止线程”的需求。

关键注意点

CLLocationManager的事件回调默认会在创建它的线程的RunLoop上触发,必须保证该线程的RunLoop处于活跃状态,不能被无限阻塞——这是你的代码无法触发事件的核心原因。

内容的提问来源于stack exchange,提问作者anon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:13:24