C#自动重置事件未释放

C#自动重置事件未释放,c#,ios,xamarin,autoresetevent,C#,Ios,Xamarin,Autoresetevent,使用Xamarin.Forms(用于iOS)我尝试实现功能,以等待用户确认已设置地理位置权限,然后再继续 我试图实现这一点的方法是让线程等待,直到使用AutoResetEvent触发事件 主要问题(我相信)在于以下代码: manager.AuthorizationChanged += (object sender, CLAuthorizationChangedEventArgs args) => { Console.WriteLine ("Authorization change

使用Xamarin.Forms(用于iOS)我尝试实现功能,以等待用户确认已设置地理位置权限,然后再继续

我试图实现这一点的方法是让线程等待,直到使用
AutoResetEvent
触发事件

主要问题(我相信)在于以下代码:

manager.AuthorizationChanged += (object sender, CLAuthorizationChangedEventArgs args) => {

    Console.WriteLine ("Authorization changed to: {0}", args.Status);

    if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) {
        tcs.SetResult (args.Status == CLAuthorizationStatus.AuthorizedAlways || args.Status == CLAuthorizationStatus.AuthorizedWhenInUse);
    } else {
        tcs.SetResult (args.Status == CLAuthorizationStatus.Authorized);
    }

    _waitHandle.Set ();
};

manager.Failed += (object sender, Foundation.NSErrorEventArgs e) => {

    Console.WriteLine ("Authorization failed");

    tcs.SetResult (false);

    _waitHandle.Set ();
};

if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) {
    manager.RequestWhenInUseAuthorization ();
}

_waitHandle.WaitOne ();
您可以在下面找到完整的类:

public class LocationManager : ILocationManager
{
    static EventWaitHandle _waitHandle = new AutoResetEvent (false);

    private TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();

    public LocationManager ()
    {
    }

    public Task<bool> IsGeolocationEnabledAsync()
    {
        Console.WriteLine (String.Format("Avaible on device: {0}", CLLocationManager.LocationServicesEnabled));
        Console.WriteLine (String.Format("Permission on device: {0}", CLLocationManager.Status));

        if (!CLLocationManager.LocationServicesEnabled) {
            tcs.SetResult (false);
        } else if (CLLocationManager.Status == CLAuthorizationStatus.Denied || CLLocationManager.Status == CLAuthorizationStatus.Restricted) {
            tcs.SetResult (false);
        } else if (CLLocationManager.Status == CLAuthorizationStatus.NotDetermined) {

            Console.WriteLine ("Waiting for authorisation");

            CLLocationManager manager = new CLLocationManager ();

            manager.AuthorizationChanged += (object sender, CLAuthorizationChangedEventArgs args) => {

                Console.WriteLine ("Authorization changed to: {0}", args.Status);

                if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) {
                    tcs.SetResult (args.Status == CLAuthorizationStatus.AuthorizedAlways || args.Status == CLAuthorizationStatus.AuthorizedWhenInUse);
                } else {
                    tcs.SetResult (args.Status == CLAuthorizationStatus.Authorized);
                }

                _waitHandle.Set ();
            };

            manager.Failed += (object sender, Foundation.NSErrorEventArgs e) => {

                Console.WriteLine ("Authorization failed");

                tcs.SetResult (false);

                _waitHandle.Set ();
            };

            if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) {
                manager.RequestWhenInUseAuthorization ();
            }

            _waitHandle.WaitOne ();

            Console.WriteLine (String.Format ("Auth complete: {0}", tcs.Task.Result));

        } else {
            if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) {
                tcs.SetResult (CLLocationManager.Status == CLAuthorizationStatus.AuthorizedAlways || CLLocationManager.Status == CLAuthorizationStatus.AuthorizedWhenInUse);
            } else {
                tcs.SetResult (CLLocationManager.Status == CLAuthorizationStatus.Authorized);
            }
        }

        return tcs.Task;
    }
}
公共类位置管理器:ILocationManager
{
静态EventWaitHandle _waitHandle=new AutoResetEvent(false);
私有TaskCompletionSource tcs=新TaskCompletionSource();
公共场所经理()
{
}
公共任务IsGeolocationEnabledAsync()
{
Console.WriteLine(String.Format(“在设备上可用:{0}”,CLLocationManager.LocationServicesEnabled));
Console.WriteLine(String.Format(“设备上的权限:{0}”,CLLocationManager.Status));
如果(!CLLocationManager.LocationServicesEnabled){
tcs.SetResult(假);
}else if(CLLocationManager.Status==CLAuthorizationStatus.Denied | | CLLocationManager.Status==CLAuthorizationStatus.Restricted){
tcs.SetResult(假);
}else if(CLLocationManager.Status==CLAuthorizationStatus.NotDetermined){
Console.WriteLine(“等待授权”);
CLLocationManager=newcllocationmanager();
manager.AuthorizationChanged+=(对象发送方、CLAuthorizationChangedEventArgs)=>{
Console.WriteLine(“授权更改为:{0}”,args.Status);
if(UIDevice.CurrentDevice.CheckSystemVersion(8,0)){
tcs.SetResult(args.Status==CLAuthorizationStatus.authorizedAllways | | args.Status==CLAuthorizationStatus.AuthorizedWhenInUse);
}否则{
tcs.SetResult(args.Status==CLAuthorizationStatus.Authorized);
}
_Set();
};
失败的+=(对象发件人,基础.nSerrReErrARGES E)= > {
Console.WriteLine(“授权失败”);
tcs.SetResult(假);
_Set();
};
if(UIDevice.CurrentDevice.CheckSystemVersion(8,0)){
manager.requestwhenUseAuthorization();
}
_waitHandle.WaitOne();
Console.WriteLine(String.Format(“Auth complete:{0}”,tcs.Task.Result));
}否则{
if(UIDevice.CurrentDevice.CheckSystemVersion(8,0)){
tcs.SetResult(CLLocationManager.Status==CLAuthorizationStatus.AuthorizedAlways | | CLLocationManager.Status==CLAuthorizationStatus.AuthorizedWhenInUse);
}否则{
tcs.SetResult(CLLocationManager.Status==CLAuthorizationStatus.Authorized);
}
}
返回tcs.Task;
}
}
它工作正常,只是我不明白为什么
manager.AuthorizationChanged
manager.Failed
事件似乎永远不会被触发,因此当状态未确定时,线程永远不会释放

非常感谢您的任何帮助或指点。

如果没有这些帮助或指点,您将无法确定问题所在。但是你的代码中肯定有一个明显的设计缺陷,我希望解决这个缺陷能解决你的问题

有什么缺点?你在等待任何事情。您编写了一个显然应该表示异步操作的方法-它的名称中有“Async”,并返回一个
Task
,而不是
bool
-然后您以这样一种方式编写该方法:返回的
Task
将始终完成,而不管采用哪种代码路径

为什么这么糟糕?好的,除了完全无法利用您正在实现的接口的异步方面这一简单事实之外,您正在使用的
CLLocationManager
类很可能希望能够在调用
IsGeolocationEnabledAsync()
方法的同一线程中运行。由于此方法在引发事件之前不会返回,并且在方法返回之前无法引发事件,因此存在死锁

IMHO,这就是你的类应该如何实现的:

public class LocationManager : ILocationManager
{
    public async Task<bool> IsGeolocationEnabledAsync()
    {
        bool result;

        Console.WriteLine (String.Format("Avaible on device: {0}", CLLocationManager.LocationServicesEnabled));
        Console.WriteLine (String.Format("Permission on device: {0}", CLLocationManager.Status));

        if (!CLLocationManager.LocationServicesEnabled) {
            result = false;
        } else if (CLLocationManager.Status == CLAuthorizationStatus.Denied || CLLocationManager.Status == CLAuthorizationStatus.Restricted) {
            result = false;
        } else if (CLLocationManager.Status == CLAuthorizationStatus.NotDetermined) {
            TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();

            Console.WriteLine ("Waiting for authorisation");

            CLLocationManager manager = new CLLocationManager ();

            manager.AuthorizationChanged += (object sender, CLAuthorizationChangedEventArgs args) => {

                Console.WriteLine ("Authorization changed to: {0}", args.Status);

                if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) {
                    tcs.SetResult (args.Status == CLAuthorizationStatus.AuthorizedAlways || args.Status == CLAuthorizationStatus.AuthorizedWhenInUse);
                } else {
                    tcs.SetResult (args.Status == CLAuthorizationStatus.Authorized);
                }
            };

            manager.Failed += (object sender, Foundation.NSErrorEventArgs e) => {

                Console.WriteLine ("Authorization failed");

                tcs.SetResult (false);
            };

            if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) {
                manager.RequestWhenInUseAuthorization ();
                result = await tcs.Task;
            } else {
                result = false;
            }

            Console.WriteLine (String.Format ("Auth complete: {0}", tcs.Task.Result));

        } else {
            if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) {
                result = CLLocationManager.Status == CLAuthorizationStatus.AuthorizedAlways || CLLocationManager.Status == CLAuthorizationStatus.AuthorizedWhenInUse;
            } else {
                result = CLLocationManager.Status == CLAuthorizationStatus.Authorized;
            }
        }

        return result;
    }
}
公共类位置管理器:ILocationManager
{
公共异步任务IsGeolocationEnabledAsync()
{
布尔结果;
Console.WriteLine(String.Format(“在设备上可用:{0}”,CLLocationManager.LocationServicesEnabled));
Console.WriteLine(String.Format(“设备上的权限:{0}”,CLLocationManager.Status));
如果(!CLLocationManager.LocationServicesEnabled){
结果=假;
}else if(CLLocationManager.Status==CLAuthorizationStatus.Denied | | CLLocationManager.Status==CLAuthorizationStatus.Restricted){
结果=假;
}else if(CLLocationManager.Status==CLAuthorizationStatus.NotDetermined){
TaskCompletionSource tcs=新的TaskCompletionSource();
Console.WriteLine(“等待授权”);
CLLocationManager=newcllocationmanager();
manager.AuthorizationChanged+=(对象发送方、CLAuthorizationChangedEventArgs)=>{
Console.WriteLine(“授权更改为:{0}”,args.Status);
if(UIDevice.CurrentDevice.CheckSystemVersion(8,0)){
tcs.SetResult(args.Status==CLAuthorizationStatus.authorizedAllways | | args.Status==CLAuthorizationStatus.AuthorizedWhenInUse);
}否则{
tcs.SetResult(args.Status==CLAuthorizationStatus.Authorized);
}
};
失败的+=(对象发件人,基础.nSerrReErrARGES E)= > {
Console.WriteLine(“Auth