С помощью асинхронного повторного входа используйте оригинальный асинхронный вызов? [Дубликат]

Попробуйте удалить pip и установить get-pip.py. Кажется, это ошибка в версии 3.6 для Windows. https://github.com/pypa/pip/issues/3964

Здесь также сообщается. pip install jupyter: «Невозможно найти искатель для« pip._vendor.distlib »& quot;

12
задан Haspemulator 9 April 2013 в 19:39
поделиться

5 ответов

У меня есть сообщение в блоге, в котором описывается несколько подходов к конструкции async .

Я рекомендую асинхронный заводский метод, описанный Ридом, но иногда это невозможно (например, , внедрение зависимости). В этих случаях вы можете использовать асинхронный шаблон инициализации следующим образом:

public sealed class MyType
{
    public MyType()
    {
        Initialization = InitializeAsync();
    }

    public Task Initialization { get; private set; }

    private async Task InitializeAsync()
    {
        // Asynchronously initialize this instance.
        await Task.Delay(100);
    }
}

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

await myTypeInstance.Initialization;

Обратите внимание, что если Initialization уже завершено, выполнение (синхронно) продолжается после await.

< hr>

Если вам действительно нужно асинхронное свойство , у меня тоже есть сообщение в блоге. Ваша ситуация звучит так, как будто это может выиграть от AsyncLazy<T>:

public sealed class MyClass
{
    public MyClass()
    {
        MyProperty = new AsyncLazy<int>(async () =>
        {
            await Task.Delay(100);
            return 13;
        });
    }

    public AsyncLazy<int> MyProperty { get; private set; }
}
28
ответ дан Stephen Cleary 21 August 2018 в 22:09
поделиться

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

Лучший подход к методу инициализации:

private async Task<bool> InitializeAsync()
{
    try{
        // Initialize this instance.
    }

    catch{
        // Handle issues
        return await Task.FromResult(false);
    }

    return await Task.FromResult(true);
}

Это будет использовать инфраструктуру async для инициализации вашего объекта , но затем он вернет логическое значение.

Почему это лучший подход? Во-первых, вы не заставляете задерживать свой код, который ИМХО полностью поражает целью использования инфраструктуры async. Во-вторых, это хорошее правило, чтобы вернуть что-то из метода асинхронности. Таким образом, вы знаете, действительно ли ваш асинхронный метод работал / делал то, что предполагалось. Возвращение только задачи - это эквивалент возвращаемого значения void по неасинхронному методу.

1
ответ дан John Doeses 21 August 2018 в 22:09
поделиться
  • 1
    await Task.Delay в моем ответе является заполнителем для «выполнять асинхронную работу здесь для инициализации экземпляра». В фактическом коде не будет Task.Delay. – Stephen Cleary 3 May 2016 в 02:09
  • 2
    Я чувствую, что ваш ответ еще хуже, так как вы не поняли, что вы делаете, и что вы показываете, так это то, что вы должны задерживать задержки для получения асинхронного поведения во время инициализации / построения. Вы должны иметь в виду, что любой из всех уровней опыта может видеть ваш пост, и вы не получили практически никакой полезной информации в своем ответе и продемонстрировали плохое кодирование без ясности. Другими словами, кто-то новый для асинхронной структуры увидит ваш ответ и выполнит задержки в своем коде, чтобы получить инициализацию / построение async. – John Doeses 3 May 2016 в 15:50
  • 3
    @StephenCleary, вы оба правы ;-) – Simon_Weaver 6 December 2017 в 22:37

Вы можете использовать мой контейнер [y0] AsyncContainer IoC, который поддерживает тот же самый сценарий, что и вы.

Он также поддерживает другие удобные сценарии, такие как инициализаторы асинхронизации, условные фабрики времени выполнения, зависят от асинхронных и синхронных заводских функций

//The email service factory is an async method
public static async Task<EmailService> EmailServiceFactory() 
{
  await Task.Delay(1000);
  return new EmailService();
}

class Service
{
     //Constructor dependencies will be solved asynchronously:
     public Service(IEmailService email)
     {
     }
} 

var container = new Container();
//Register an async factory:
container.Register<IEmailService>(EmailServiceFactory);

//Asynchronous GetInstance:
var service = await container.GetInstanceAsync<Service>();

//Safe synchronous, will fail if the solving path is not fully synchronous:
var service = container.GetInstance<Service>();
2
ответ дан rafael 21 August 2018 в 22:09
поделиться

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

После этого ваш заводский метод может вернуть Task<ServiceProvider>, что позволит вам выполнить инициализацию асинхронно, но не возвращать сконструированные ServiceProvider до тех пор, пока ImportantValue не будет (асинхронно) вычисляться.

Это позволит вашим пользователям писать код наподобие:

var sp = await ServiceProvider.CreateAsync();
int iv = sp.ImportantValue; // Will be initialized at this point
4
ответ дан Reed Copsey 21 August 2018 в 22:09
поделиться
  • 1
    Извините, я забыл упомянуть в вопросе о том, что мой класс должен реализовать интерфейс и предназначен для использования только через интерфейс. Это исключает статический заводский метод. – Haspemulator 9 April 2013 в 17:44
  • 2
    @Haspemulator В этом случае вы всегда будете иметь фабричный метод где-нибудь (вы не можете построить интерфейс) - это делает это проще ... – Reed Copsey 9 April 2013 в 18:08
  • 3
    У вас есть пример того, как будет выглядеть CreateAsync – Demodave 11 June 2017 в 17:40

Это небольшая модификация шаблона @StephenCleary инициализации async.

Разница в том, что вызывающему абоненту не нужно «запоминать» await InitializationTask или даже знать что-либо о initializationTask (на самом деле теперь он изменен на закрытый).

Способ, которым он работает, заключается в том, что в каждом методе, который использует инициализированные данные, есть начальный вызов await _initializationTask. Это мгновенно возвращается во второй раз, потому что сам объект _initializationTask будет иметь логический набор (IsCompleted, который проверяет механизм ожидания), поэтому не стоит беспокоиться об инициализации несколько раз.

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

public sealed class MyType
{
    public MyType()
    {
        _initializationTask = InitializeAsync();
    }

    private Task _initializationTask;

    private async Task InitializeAsync()
    {
        // Asynchronously initialize this instance.
        _customers = await LoadCustomersAsync();
    }

    public async Task<Customer> LookupCustomer(string name)
    {
         // Waits to ensure the class has been initialized properly
         // The task will only ever run once, triggered initially by the constructor
         // If the task failed this will raise an exception
         // Note: there are no () since this is not a method call
         await _initializationTask;

         return _customers[name];
    }

    // one way of clearing the cache
    public void ClearCache()
    {
         InitializeAsync();
    }

    // another approach to clearing the cache, will wait until complete
    // I don't really see a benefit to this method since any call using the
    // data (like LookupCustomer) will await the initialization anyway
    public async Task ClearCache2()
    {
         await InitializeAsync();
    }
 }
2
ответ дан Simon_Weaver 21 August 2018 в 22:09
поделиться
  • 1
    Ничего себе, ладно, я все это делал неправильно, спасибо. Как вы обрабатываете проверку завершенной инициализации? – Ryan The Leach 14 March 2018 в 06:38
  • 2
    Важная вещь в моем ответе (которая не была очевидна мне в какой-то момент) - это осознание того, что вы можете сохранить ссылку на задание и что фактическая задача выполняется только один раз и независимо от результата кэшируется так, какой бы метод вы ни называли вниз цепочка попытается получить доступ к результату задачи, и если есть исключение, это будет просто волшебный пузырь каждый раз. – Simon_Weaver 14 March 2018 в 06:42
  • 3
    Хорошо, я закончил обматывание ожиданий в методе GuardInit (), который ждет, но также проверяет результат, если он был закончен, что позволяет повторить попытку или создать приложение в зависимости от серьезности результата. Спасибо за ответ. – Ryan The Leach 14 March 2018 в 06:51
  • 4
    Конечно :) Вы получаете одно длинное предложение, когда оно набирается на моем телефоне! Мне нравится идея автоматического повтора - я полагаю, это зависит от того, что она делает. – Simon_Weaver 14 March 2018 в 06:52
Другие вопросы по тегам:

Похожие вопросы: