Когда я ответил на ваш previous question, я предположил, что у вас есть требование использовать объект TaskCompletionSource, поэтому я сожалею, если он отправил вас в неправильном направлении. Поскольку Paulo сказал, что обычно вам не нужно использовать TaskCompletionSource с кодом async/await, но вам нужно немного понять, как его использовать.
Вызов Result Задача приведет к блокировке потока, теперь в потоке, отличном от UI, это не такая проблема (просто не идеальная), но в потоке пользовательского интерфейса это фактически остановит ваш UI from responding, пока задача не будет завершен, если предположить, что он просто не прекращается полностью из-за тупика.
Главное, чтобы узнать, как использовать async/await в среде пользовательского интерфейса, потому что для его работы вы также используете async/wait везде, иначе вы в конечном итоге попытаетесь использовать Task.Result для доступа к вашим данным и получения заблокированный поток пользовательского интерфейса для ваших проблем.
Это хороший гид стартер - https://msdn.microsoft.com/en-us/magazine/jj991977.aspx
Теперь предположим, что вы тянете code
со страницы, как это (мощеной из code samples на GitHub), а затем извлечения лексем.
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var content = webBrowser1.DocumentText;
var regex = new Regex(@"\<title\>(.+?)=(.+?)\</title\>");
var match = regex.Match(content);
if (!match.Success || match.Groups.Count != 3)
return;
switch (match.Groups[1].Value.ToLowerInvariant())
{
case "code": // we have a code
var code = match.Groups[2].Value;
var config = new ApiConfiguration(Configuration.ClientId, Configuration.ClientSecret, Configuration.RedirectUrl);
var service = new OAuthService(config, new WebRequestFactory(config));
var tokens = service.GetTokensAsync(code).Result; // <= blocking
_keyService.OAuthResponse = tokens;
break;
case "error": // user probably said "no thanks"
webBrowser1.Navigate(_logoffUri);
break;
}
}
однако ваш код блокировка на .Result
Что вам нужно сделать, это использовать асинхронные/ОЖИДАНИЕ всего путь, однако при использовании ждать жалуется на отсутствии асинхронного о методе, так , просто добавьте его; да, это разрешено, и есть много статей и сообщений в блогах об этом, что catch people new to async/await в интерфейсе winforms/wpf.
например.
// we add async to the callback - yup it's allowed
private async void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var content = webBrowser1.DocumentText;
var regex = new Regex(@"\<title\>(.+?)=(.+?)\</title\>");
var match = regex.Match(content);
if (!match.Success || match.Groups.Count != 3)
return;
switch (match.Groups[1].Value.ToLowerInvariant())
{
case "code": // we have a code
var code = match.Groups[2].Value;
var config = new ApiConfiguration(Configuration.ClientId, Configuration.ClientSecret, Configuration.RedirectUrl);
var service = new OAuthService(config, new WebRequestFactory(config));
var tokens = await service.GetTokensAsync(code); // <= now we can use await here => non-blocking
_keyService.OAuthResponse = tokens;
break;
case "error": // user probably said "no thanks"
webBrowser1.Navigate(_logoffUri);
break;
}
}
Я uploaded the code as gist Я надеюсь, что это помогает
@shaun_a_wilde пожалуйста, вы можете помочь? –
Какой интерфейс? если это насос сообщений, основанный как WinForms или WPF, он должен блокироваться. Почему вы используете 'Task.Run' и' TaskCompletionSource' для вызова уже асинхронного кода? –
Я отредактировал вопрос, чтобы уточнить, что это программа, которая блокируется, а не пользовательский интерфейс. (Мне нужно Ctrl Alt Delete, чтобы закончить программу). Я использую Task.Run и TaskCompletionSource, чтобы дождаться выполнения задачи. Существует синхронный вариант .GetTokens, но я экспериментирую. –