使用Xamarin.Forms(對於iOS)我嘗試實現功能,以等待用戶確認已設置GeoLocation權限,然後再繼續。C#AutoResetEvent沒有發佈
我試圖做到這一點的方法是讓線程等待,直到使用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
事件似乎永遠不會被解僱,因此當狀態爲未確定時線程永遠不會釋放。
任何幫助或指針,不勝感激。
是的,代碼根本沒有任何意義 - 尤其是,考慮到'RequestWhenInUseAuthorization'必須在UI線程上調用。 所以他應該等待(隱式)在UI線程上的用戶輸入;例如。點擊允許或取消。 – nullpotent
嘿,謝謝你的時間和詳細的答案。我學到了很多 !我注意到的一件事是AutoResetEvent不再使用。我嘗試在'C#等待事件完成'之後使用它。如果你不介意我再問一個問題,'result = await tcs.Task;'在這個上下文中是否做了類似於AutoResetEvent的事情,或者是否應該使用AutoResetEvent來防止多線程在使用? (請注意,我仍然是C#中的新手) – RVandersteen
@RVandersteen:_「does'result = await tcs.Task;'在此上下文中執行與AutoResetEvent類似的操作」 - - 取決於您認爲的「相似」 。它在類似的意義上是,該方法中的代碼暫時「暫停」,直到事件發出信號。但是''AutoResetEvent''(ARE)通過使_thread_本身「暫停」來實現這一點,而使用'await'則不會。 –