Я не очень разбираюсь в TPL.
Рассмотрим следующий сценарий:
У меня есть следующие занятия:
public class Contact
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
public Company Company { get; set; }
}
public class Company
{
public int Id { get; set; }
public string Name { get; set; }
}
Теперь у меня есть следующий фрагмент кода
Task<Contact> contactDetails = r.FirstOrDefaultAsync<Contact>();
Task<Company> companyDetails = r.FirstOrDefaultAsync<Company>();
Теперь я хочу заполнить свойство Company результатом companyDetails. что-то в этом роде (пожалуйста, проверьте ниже)
contactDetails.Company = companyDetails
Я хочу сделать это без вызова функции ожидания для поддержки асинхронности.
Кто-нибудь, пожалуйста, помогите мне в этом?
Да, мы можем сделать так, чтобы получить результат и присвоить его. Но это не то, что я ищу. Я хочу сделать это без блочного потока, пока не использую await.
@Saadi Не могли бы вы пояснить, почему вы не хотите использовать await?
@ pere57, уже выделено в моем вышеупомянутом комментарии, что await block thread,
Downvoters - скажите, пожалуйста, что не так в этом вопросе?
Task <T> не является фактическим объектом. Как сказано выше, это обещание получить объект. Поэтому, когда у вас есть Task <T>, вы не можете назначать свойства объекту T. Task <T> может не возвращать объект T. Это может вызвать исключение.
Так что вам нужно дождаться Задачи и получить результат, прежде чем работать с объектом. Хотя вы можете поместить это в другую задачу, и тогда она будет выполняться только при ожидании задачи, что я показал.
@Saadi await не блокирует поток. Это асинхронное ожидание, а не ожидание с блокировкой. await - именно то, что вам нужно.





Скажем, вы создали асинхронный метод, как показано ниже:
public async Task<Contact> GetContact()
{
R r = new R();
Contact contactDetails = await r.FirstOrDefaultAsync<Contact>();
Company companyDetails = await r.FirstOrDefaultAsync<Company>();
contactDetails.Company = companyDetails;
Console.WriteLine("3");
return contactDetails;
}
Это не будет выполнено, пока вы не дождетесь этого GetContact. Так, например, если мы вызовем его, используя приведенный ниже код:
Console.WriteLine("1");
Task<Contact> getContactTask = GetContact();
Console.WriteLine("2");
Contact contact = await getContactTask; // the code is now executed
Console.WriteLine("4");
Консоль покажет:
1
2
3
4
Согласно вашему комментарию, я думаю, что это то, что вы хотите. Get contact and get company не будет выполняться, пока вы не вызовете await в методе GetContact.
Кроме того, если вы хотите выполнить как получение контакта, так и параллельную работу компании, вы можете использовать следующее:
public async Task<Contact> GetCompanyParallel()
{
R r = new R();
Task<Contact> contactDetailsTask = r.FirstOrDefaultAsync<Contact>();
Task<Company> companyDetailsTask = r.FirstOrDefaultAsync<Company>();
await Task.WhenAll(contactDetailsTask, companyDetailsTask);
Contact contactDetails = await contactDetailsTask;
contactDetails.Company = await companyDetailsTask;
return contactDetails;
}
companyDetailsотносится к типуTask<Company>, поэтому вы не можете просто назначить его переменной типаCompany. Это больше похоже на обещание, что вы получите результат, как только оно будет выполнено. Вы можете вызватьTask<T>.Resultдля получения результата, однако имейте в виду, что вызывающий поток будет блокироваться до тех пор, пока задача не будет завершена, чего вы хотите избежать при использовании TPL ...