Использование Xamarin.Forms (для iOS) Я пытаюсь реализовать функциональность, чтобы дождаться подтверждения пользователем разрешения на геолокацию, которое должно быть установлено до продолжения.C# AutoResetEvent не освобождает
Способ, которым я пытаюсь достичь этого, заключается в том, что Thread продолжает до тех пор, пока событие не будет запущено с использованием 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;
}
}
Он отлично работает за исключением того, что я не могу понять почему событие manager.AuthorizationChanged
или manager.Failed
, кажется, никогда не срабатывает, и, таким образом, нить никогда не будет выпущена, если статус не определен.
Любая помощь или указатели с благодарностью.
Yup, код не имеет никакого смысла - особенно, учитывая, что 'RequestWhenInUseAuthorization' должен быть вызван в потоке пользовательского интерфейса. Поэтому он должен ждать (неявно) для пользовательского ввода в потоке пользовательского интерфейса; например. нажмите «Разрешить» или «Отменить». – nullpotent
Эй, спасибо за ваше время и подробный ответ. Я многому научился ! Одна вещь, которую я заметил, это то, что AutoResetEvent больше не используется. Я попытался использовать это после некоторых поисковых запросов для «C# ждать окончания события». Если вы не возражаете, чтобы я задал еще один вопрос, делает ли'result = wait tcs.Task? 'В этом контексте сделать что-то похожее на AutoResetEvent или использовать AutoResetEvent в случае запуска нескольких потоков? (Обратите внимание, что я все еще новичок в C#) – RVandersteen
@RVandersteen: _ "does' result = wait tcs.Task; 'в этом контексте сделать что-то похожее на AutoResetEvent" _ - это зависит от того, что вы считаете "похожим" , Это похоже в том смысле, что код _in этого метода_ временно «приостанавливается» до тех пор, пока событие не будет сигнализировано. Но все равно, что «AutoResetEvent» (ARE) делает это, вызывая «приостановку» _thread_, тогда как использование 'await' не делает. –