我有以下内容:
public async Task<bool> SearchForUpdatesAsync()
{
return await TaskEx.Run(() =>
{
if (!ConnectionChecker.IsConnectionAvailable())
return false;
// Check for SSL and ignore it
ServicePointManager.ServerCertificateValidationCallback += delegate { return (true); };
var configurations = UpdateConfiguration.Download(UpdateConfigurationFileUri, Proxy);
var result = new UpdateResult(configurations, CurrentVersion,
IncludeAlpha, IncludeBeta);
if (!result.UpdatesFound)
return false;
_updateConfigurations = result.NewestConfigurations;
double updatePackageSize = 0;
foreach (var updateConfiguration in _updateConfigurations)
{
var newPackageSize = GetUpdatePackageSize(updateConfiguration.UpdatePackageUri);
if (newPackageSize == null)
throw new SizeCalculationException(_lp.PackageSizeCalculationExceptionText);
updatePackageSize += newPackageSize.Value;
_packageOperations.Add(new UpdateVersion(updateConfiguration.LiteralVersion),
updateConfiguration.Operations);
}
TotalSize = updatePackageSize;
return true;
});
}
如您所见,我正在使用 Microsoft.Bcl 。 现在在我的其他课程中,我用正常的 void :
编写了这段代码TaskEx.Run(async delegate
{
// ...
_updateAvailable = await _updateManager.SearchForUpdatesAsync();
MessageBox.Show("Test");
});
我遇到的问题是它执行_updateAvailable = await _updateManager.SearchForUpdatesAsync();
然后它不会继续该线程,它只是停止,好像在该调用之后没有任何内容。一段时间后,Visual Studio也会告诉我:Thread ... exited with code 259
,所以似乎还有一些东西存在。
我通过它进行调试以搜索可能被吞下的任何异常,但没有,一切正常并且执行返回 - 陈述。 这就是我不明白的地方,我从未看到MessageBox和/或没有代码超出此行的执行。 在我和一些朋友交谈后,他们确认不应该这样做。在实现async-await时我犯了一个可怕的错误吗?
在此先感谢,实际上我只能说这个,我没有更多的信息,我尽可能地感谢任何提示和帮助。
答案 0 :(得分:5)
您遇到的主要问题是您在TaskEx.Run()
中不必要地包装了您的方法,并且您可能在某处遇到了死锁。
您的方法签名目前是:
public async Task<bool> SearchForUpdatesAsync()
这意味着以下内容:
async
- &gt;实际上没有做任何事情,但提供了一个“抬头”,可以在此方法中调用await
,并且此方法可以用作可运行的任务。
Task
- &gt;此方法返回可在线程池上异步运行的可运行任务<bool>
- &gt;这个方法实际上在等待时返回bool。
await TaskEx.Run()
是不必要的,因为这表示运行此方法,然后在值可用之后才返回。这很可能导致同步问题。删除此构造将使您的方法正常工作,但是您会注意到现在您没有理由甚至包括async
运算符或Task<T>
部分,因为该方法实际上是同步的。通常,如果您要在方法签名上调用async
,那么您只会在方法签名上使用await
标识符。
相反,您有两种选择。
SearchForUpdates()
时,您可以将其包装在Task<bool>.Run()
中以异步方式运行(或等效的Bcl)BackgroundWorker
并在其中调用此方法。关于使用async-await模式,我认为这是一篇很好的文章,可用于确保您遵循最佳实践:https://msdn.microsoft.com/en-us/magazine/jj991977.aspx
答案 1 :(得分:1)
最佳做法是在图层中一直保持异步,然后在最终使用网站上调用等待或不太理想的 .Wait()/ .Result 。
此外,尝试将UI调用与后端工作分开,因为您可能会遇到同步/线程上下文问题。
public class WinFormsCode
{
private async Task WinsFormCodeBehindMethodAsync()
{
var updatesAvailable = await _updateManager.SearchForUpdatesAsync();
MessageBox.Show("Updates Available: " + updatesAvailable.ToString());
}
private void WinsFormCodeBehindMethodSync()
{
var updatesAvailable = _updateManager.SearchForUpdatesAsync().Result;
MessageBox.Show("Updates Available: " + updatesAvailable.ToString());
}
}
public class UpdateManager
{
public async Task<bool> SearchForUpdatesAsync()
{
return true;
}
}