2013-05-10 2 views
-2

У меня есть два метода:Как подождать до конца и только потом продолжить?

private async Task<GeoCoordinate> CenterMapOnMyLocation() 
    { 
     Geolocator myGeolocator = new Geolocator(); 
     Geoposition myGeoposition = await myGeolocator.GetGeopositionAsync();   
     Geocoordinate myGeocoordinate = myGeoposition.Coordinate; 
     GeoCoordinate myGeoCoordinate = 
      ConvertGeocoordinate(myGeocoordinate); 

     MapCenter = myGeoCoordinate; 
     if (MyLocation.Latitude == 0 && MyLocation.Longitude == 0) 
     { 
      MyLocation = MapCenter; 
     } 

     return myGeoCoordinate; 
    } 

и

private void GetClosestLocations(GeoCoordinate myLocation) 
    { 
     var locations = new ObservableCollection<PushPinModel> 
        { 
         new PushPinModel 
          { 
           Location = new GeoCoordinate(51.569593, 10.103504), 
           LocationName = "1" 
          }, 
         new PushPinModel 
          { 
           Location = new GeoCoordinate(-45.569593, 1.103504), 
           LocationName = "2" 
          }, 
         new PushPinModel 
          { 
           Location = new GeoCoordinate(0, 0), 
           LocationName = "3" 
          } 
        }; 
     foreach (var location in locations) 
     { 
      location.DistanceToMyLocation = HaversineDistance(myLocation, location.Location); 
     } 

     Treks = new ObservableCollection<PushPinModel>(locations.OrderBy(l => l.DistanceToMyLocation).Take(2).ToList()); 
    } 

и в конструкторе у меня есть что-то вроде этого:

public NearbyControlViewModel() 
    { 
     var test = CenterMapOnMyLocation(); 
     GetClosestLocations(test); 
    } 

Теперь моя проблема заключается в том, что, когда второй метод вызываемый в конструкторе, переменная «test» еще не инициализирована ... потому что она асинхронна. То, что я хочу сделать, - это подождать, пока он будет инициализирован, и после этого вызовите второй метод. Если я вызову свой второй метод из метода async, я получу исключения: InvalidOperationException - Collection находится в режиме, недоступном для записи. Значение «Treks» привязано к MapItemsControl. Поэтому я думаю, что проблема связана с потоками.

+0

Взгляните на тему «безопасная резьба». Особенно посмотрите на тупики и условия гонки. – jAC

+0

Скомпилирует ли ваш код? 'CenterMapOnMyLocation' возвращает' Task 'Но' GetClosestLocations' принимает 'GeoCoordinate' – I4V

+0

Да, он компилируется. –

ответ

1

Если это не конструктор:

public async Task SomeMethod() 
{ 
    var test = await CenterMapOnMyLocation(); 
    GetClosestLocations(test); 
} 

Но - с конструктором? возможно просто не делаем это. Попытка подождать в конструкторе может быть смертельной - особенно в некоторых контекстах синхронизации - это может зайти в тупик немедленно.

Рассмотрите возможность создания чего-то, что вы начинаете после конструктор.

+0

'async' на конструкторе? – I4V

+0

@ I4V ах, не понял, что это был конструктор! В самом деле, в этом случае: * не делайте этого *: p –

+0

Я сделал то, что вы здесь сказали: создал новый класс «SomeMethod» и вызвал его в конструкторе, но снова я получил Exception. –

0

Вы можете добавить test.Wait(); перед вызовом GetClosestLocation; в конце концов, вы получаете задачу из CenterMapOnMyLocation. (EDIT: Но, действительно, Марк прав, ожидая, что есть зло. Вероятно, вы должны реорганизовать вызов асинхронного кода вне конструктора.)

+0

Выполнение этого никогда не пройдет мимо ожидания. –

2

Вам нужно использовать асинхронную инициализацию. Я предлагаю несколько разных решений в своем blog post on async construction.

Обратите внимание, что асинхронный код заставляет у вас лучший дизайн пользовательского интерфейса. I.e., вы должны спроектировать какое-то состояние «до того, как карта будет сосредоточена» для вашего пользовательского интерфейса. Сначала пользовательский интерфейс будет запускаться в этом состоянии, а затем, когда завершена (асинхронная) инициализация, пользовательский интерфейс будет обновлен.