Есть ли способ, которым я могу ждать метод, который в настоящее время не асинхронный? - PullRequest
0 голосов
/ 06 февраля 2019

У меня есть этот код, который запускается после нажатия кнопки:

    partial void DownloadPressed(NSObject sender)
    {
        Console.WriteLine("Pressed");

        BeginInvokeOnMainThread(() => {
            Label1.StringValue = "Fetching Data";
            Label2.StringValue = "Fetching Data";
            Label3.StringValue = "Fetching Data";
        );
        DownloadFromAzure();
        Label1.StringValue = "Phrases: " + psNet.Count;
        Label2.StringValue = "CategorySource: " + csNet.Count;
        Label3.StringValue = "CategoryGroupSource: " + cgsDb;
    } 

Я пробовал несколько разных вещей, но не могу отобразить сообщения Fetching Data.Я предполагаю, что это потому, что все работает в одном потоке без ожидания.

Может кто-нибудь дать мне совет о том, как я могу запустить метод в ожидании.

    private static void DownloadFromAzure()
    {
        // Some database and HTTP calls here

    }

Ответы [ 3 ]

0 голосов
/ 06 февраля 2019

Если я правильно вас понимаю, вы хотите превратить синхронный вызов в DownloadFromAzure() в ожидаемый вызов.

Существует несколько способов сделать это, включая изменение DownloadFromAzure() в асинхронный метод.

Но если это не лучший подход (который может иметь место), вы можете просто обернуть его в Task:

await Task.Run(() => DownloadFromAzure());

Обновление,из-за комментария:

partial void DownloadPressed(NSObject sender)
{
    Console.WriteLine("Pressed");

    DoDownloadAsync();
}

private async void DoDownloadAsync()
{
    BeginInvokeOnMainThread(() => {
        Label1.StringValue = "Fetching Data";
        Label2.StringValue = "Fetching Data";
        Label3.StringValue = "Fetching Data";
    );

    await Task.Run(() => DownloadFromAzure());

    Label1.StringValue = "Phrases: " + psNet.Count;
    Label2.StringValue = "CategorySource: " + csNet.Count;
    Label3.StringValue = "CategoryGroupSource: " + cgsDb;
}

Обратите внимание, что это подход «забей и забудь», который может использоваться только в этой форме, если DoDownloadAsync() делает надлежащую обработку ошибок под свою ответственность (чтоможет быть включено в DownloadFromAzure() здесь), а вызывающий абонент (DownloadPressed здесь) не заботится о отслеживании прогресса Task!В любом другом случае DoDownloadAsync() должен вернуть Task, который он ожидает, для того, чтобы вызывающий мог отслеживать.

См., Например, здесь для более подробного обсуждения: async / await - когдавернуть задание против void?

0 голосов
/ 06 февраля 2019

Ответ НЕТ

В официальной документации для ключевого слова await:

Оператор await применяется к задачев асинхронном методе для вставки точки приостановки при выполнении метода до завершения ожидаемой задачи.Задача представляет текущую работу.

await может использоваться только в асинхронном методе , модифицированном ключевым словом async.Такой метод, определенный с использованием модификатора async и обычно содержащий одно или несколько выражений ожидания, называется асинхронным методом.

Итак, вы можете выбрать следующие параметры:

  1. Сделать DownloadFromAzure() как asnyc
  2. добавить следующий фрагмент кода:

    await Task.Run(() => DownloadFromAzure())

0 голосов
/ 06 февраля 2019

э-э .. нет?

await требует, чтобы аргумент был ожидаемым .. см. https://blogs.msdn.microsoft.com/pfxteam/2011/01/13/await-anything/ как сделать свои собственные ожидаемые для вещей, которые не возвращают Task <> ...

но я не уверен, стоит ли оно того. по-прежнему требует , чтобы вы могли отслеживать условия запуска / выполнения / остановки / ошибки ожидающего задания, и, учитывая, что у вас только один линейный вызов функции, у вас, вероятно, нет такой информации под рукой.

Было бы лучше провести рефакторинг / перепроектирование DownloadFromAzure, чтобы фактически вернуть задание, которое вы можете легко ожидать.

РЕДАКТИРОВАТЬ:

в тяжелых случаях вы можетевсегда оборачивайте его с помощью Task.Run

partial async Task DownloadPressed(NSObject sender)
{
    Console.WriteLine("Pressed");

    BeginInvokeOnMainThread(() => {
        Label1.StringValue = "Fetching Data";
        Label2.StringValue = "Fetching Data";
        Label3.StringValue = "Fetching Data";
    );

    await Task.Run( () => DownloadFromAzure() );   // <-----HERE

    Label1.StringValue = "Phrases: " + psNet.Count;
    Label2.StringValue = "CategorySource: " + csNet.Count;
    Label3.StringValue = "CategoryGroupSource: " + cgsDb;
} 
...