2013-08-01 2 views
-2

Я звоню в этот статический метод входа с именем пользователя и паролем. Я хочу, чтобы он подождал, пока он не завершит загрузку downloadstringasync. За бесстрашную жизнь я не могу заставить ее подождать.Как сделать обратный вызов ждать завершения async C#

Я попытался Oldschool

while(wc.IsBusy){} //Which froze 

также попробовал разнообразие асинхронной гречихи Didnt даже компилировать

public static dbObj Login(String username, String password) 
    { 
     dbObj ret = new dbObj(); 
     String rawWebReturn = ""; 
     ret.propBag.Add(_BAGTYPE,returnTypes.Login.ToString()); 
     DateTime date = DateTime.Now; 
     WebClient wc = new WebClient(); 
     wc.DownloadStringAsync(new Uri(baseLoginURI + "uname=" + username + "&pword=" + password + "&date=" + date.ToString())); 


     wc.DownloadStringCompleted += (s,e) => {           
            if(e.Error!=null) 
             rawWebReturn = e.Error.Message; 
            else 
             rawWebReturn = e.Result; 
           }; 
     return parseWebReturn(rawWebReturn,ret);    
    } 
+2

Если вы хотите, чтобы это было синхронно, почему бы просто не вызвать синхронный метод 'DownloadString'? –

+0

Потому что он не существует в телефоне Windows. –

+3

Спасибо за разъяснение платформы. Это говорит вам кое-что. Вы не должны пытаться блокировать. –

ответ

3

Прежде всего, вы никогда не должны ждать для завершения асинхронной операции. Вместо этого продолжите выполнение после завершения функции.

EDIT: Вы должны добавить пакет NuGet Microsoft.Bcl.Async здесь.

Теперь, так как вы используете Windows Phone 8, вы можете смело использовать асинхронной здесь:

public static async dbObj Login(String username, String password) 
    { 
     dbObj ret = new dbObj(); 
     String rawWebReturn = ""; 
     ret.propBag.Add(_BAGTYPE, returnTypes.Login.ToString()); 
     DateTime date = DateTime.Now; 
     WebClient wc = new WebClient(); 
     try 
     { 
      var result = await wc.DownloadStringTaskAsync(new Uri(baseLoginURI + "uname=" + username + "&pword=" + password + "&date=" + date.ToString())); 
      return parseWebReturn(result, ret); 
     } 
     catch (Exception e) 
     { 
      return parseWebReturn(e.Message, ret); 
     } 
    } 

Асинхронный должен компилировать, потому что он просто работает. Если у вас возникли проблемы с этим, попробуйте снова с вашим фрагментом кода здесь.

Если вы хотите настроить таргетинг на Windows Phone 7, добавьте вышеупомянутый пакет NuGet, и вы сможете скомпилировать его без проблем.

+0

Нет загружаемой строки Задача Ascync для Windows-телефона в веб-клиенте –

+1

Добавить ссылка на пакет NuGet ** Microsoft.Bcl.Async **. –

+0

Спасибо, я попробую, когда вернусь с работы! –

1

Если вам нужно, чтобы блокировать поток, пока операция асинхронной не будет завершена, вы можете использовать ManualResetEvent, как это:

ManualResetEvent wait = new ManualResetEvent(false); 

wc.DownloadStringCompleted += (s,e) => {           
    // ... 

    // allow to proceed 
    wait.Set(); 
}; 

// wait until Set 
wait.WaitOne(); 

return parseWebReturn(rawWebReturn,ret); 

В общем, вы не хотите блокировать потоки, а используете обратные вызовы. Вы можете сделать это путем предоставления Action делегата вместо возвращаемого значения:

public static void Login(String username, String password, Action<dbObj> callback) 
{ 
    // ... 

    wc.DownloadStringCompleted += (s,e) => {           
           if(e.Error!=null) 
            rawWebReturn = e.Error.Message; 
           else 
            rawWebReturn = e.Result; 

           Callback(parseWebReturn(rawWebReturn, ret);); 
          }; 
} 
+0

Я REAAAALLLY хотел, чтобы ваше первое решение работало. Однако это просто зависает в ожидании :-(Для вашего второго решения возвращаемый тип должен быть dbObj –

+0

@AMR вы уверены, что «DownloadStringCompleted» на самом деле срабатывает? – McGarnagle

+0

Это не вызвано, потому что оно висит на WaitOne –

1

Если заставить ждать в потоке пользовательского интерфейса либо путем прядения while петли или с помощью ManualResetEvent.WaitOne, то вы на самом деле запирания приложения. Сетевой вызов в какой-то момент, похоже, должен касаться потока пользовательского интерфейса, но вы его заморозили = тупик.

Замораживание нити пользовательского интерфейса, как это также плохо, множеством других способов (никакие события касания не будут обработаны, обновления экрана и т. Д.).

Вам было бы лучше использовать HttpClient for Windows Phone и использовать шаблон async/await. Вы можете загрузить это из NuGet в качестве пакета Microsoft.Net.Http.

1

Вы можете переписать существующий метод WebClient с помощью Асинхронный и Await метод что-то вроде этого

public Task<string> GetRssFeed(string feedUrl) 
{ 
     var tcs = new TaskCompletionSource<string>(); 
     var client = new WebClient(); 
     client.DownloadStringCompleted += (s, e) => 
     { 
      if (e.Error == null) 
      { 
        tcs.SetResult(e.Result); 
      } 
      else 
      { 
        tcs.SetException(e.Error); 
      } 
     }; 

     client.DownloadStringAsync(new Uri(feedUrl)); 
     return tcs.Task; 

}

Так от этого вы можете ждать вашего звонка до обратного вызова не вернется. Это самый эффективный и последний способ достижения вашей функциональности.

+2

Да, это лучший способ достичь функциональности. –

+0

За исключением того, что это телефон с Windows и нет загруженной строки. Завершено –

+2

Да, есть: http://msdn.microsoft.com/en-us/library/system.net.webclient.downloadstringcompleted(v=vs.95). aspx Поддерживается в: Windows Phone OS 7.1, Windows Phone OS 7.0 –

Смежные вопросы