Попробуйте удалить pip и установить get-pip.py. Кажется, это ошибка в версии 3.6 для Windows. https://github.com/pypa/pip/issues/3964
Здесь также сообщается. pip install jupyter: «Невозможно найти искатель для« pip._vendor.distlib »& quot;
У меня есть сообщение в блоге, в котором описывается несколько подходов к конструкции 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
.
Если вам действительно нужно асинхронное свойство , у меня тоже есть сообщение в блоге. Ваша ситуация звучит так, как будто это может выиграть от 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; }
}
Я знаю, что это старый вопрос, но он первый, который появляется в 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 по неасинхронному методу.
await Task.Delay
в моем ответе является заполнителем для «выполнять асинхронную работу здесь для инициализации экземпляра». В фактическом коде не будет Task.Delay
.
– Stephen Cleary
3 May 2016 в 02:09
Вы можете использовать мой контейнер [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>();
Один из возможных вариантов заключается в том, чтобы перенести это на заводский метод вместо использования конструктора.
После этого ваш заводский метод может вернуть Task<ServiceProvider>
, что позволит вам выполнить инициализацию асинхронно, но не возвращать сконструированные ServiceProvider
до тех пор, пока ImportantValue
не будет (асинхронно) вычисляться.
Это позволит вашим пользователям писать код наподобие:
var sp = await ServiceProvider.CreateAsync();
int iv = sp.ImportantValue; // Will be initialized at this point
Это небольшая модификация шаблона @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();
}
}