В моем проекте я ссылаюсь на типы и интерфейсы из библиотеки динамических ссылок. Самое первое, что я должен сделать при использовании этой конкретной библиотеки, - это создать экземпляр EA.Repository
, который определен внутри библиотеки и служит своего рода точкой входа для дальнейшего использования.
Создание экземпляра EA.Repository repository = new EA.Repository()
выполняет некоторые сложные вещи в фоновом режиме, и я сталкиваюсь с тремя возможными результатами:
- Инстанцирование занимает некоторое время, но заканчивается успешно в конце
- Исключение выдается (или сразу, или через некоторое время)
- Инстанцирование блокируется навсегда (в этом случае я хотел бы отменить и сообщить пользователю)
Я смог придумать асинхронныйподход с использованием Task
:
public static void Connect()
{
// Do the lengthy instantiation asynchronously
Task<EA.Repository> task = Task.Run(() => { return new EA.Repository(); });
bool isCompletedInTime;
try
{
// Timeout after 5.0 seconds
isCompletedInTime = task.Wait(5000);
}
catch (Exception)
{
// If the instantiation fails (in time), throw a custom exception
throw new ConnectionException();
}
if (isCompletedInTime)
{
// If the instantiation finishes in time, store the object for later
EapManager.Repository = task.Result;
}
else
{
// If the instantiation did not finish in time, throw a custom exception
throw new TimeoutException();
}
}
(я знаю, вы, вероятно, уже можете заметить много проблем здесь. Пожалуйста, будьте терпеливы со мной ... Рекомендации будут оценены!)
Этот подход работает до сих пор - я могу смоделировать сценарий «исключения» и «тайм-аут» и получить желаемое поведение.
Однако у меня естьобозначен другой крайний случай: предположим, что задача создания экземпляра занимает достаточно много времени, чтобы истекло время ожидания, а затем выдает исключение. В этом случае я иногда получаю AggregateException
, говорящее, что задача не была выполнена.
Я изо всех сил пытаюсь найти реальное решение для этого. Я действительно не могу отменить задачу, когда истекает время ожидания, потому что создание экземпляров блокировки явно мешает мне использовать CancellationToken
подход.
Единственное, что я могу придумать, это начать наблюдать за задачей асинхронно (то есть начать другое задание) прямо перед тем, как бросить мой кастомный TimeoutException
:
Task observerTask = Task.Run(() => {
try { task.Wait(); }
catch (Exception) { }
});
throw new TimeoutException();
Конечно, если создание экземпляров действительно блокирует навсегда, у меня уже было первое задание, которое никогда не закончилось. С заданием наблюдателя теперь у меня даже есть два!
Я совершенно не уверен в этом подходе, поэтому любые советы будут приветствоваться!
Заранее большое спасибо!