等待停止线程的执行并且永远不会继续
Await stops execution of thread and never continues
我有以下内容:
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。
现在在我的另一个 class 中,我用正常的 void:
写了这段代码
TaskEx.Run(async delegate
{
// ...
_updateAvailable = await _updateManager.SearchForUpdatesAsync();
MessageBox.Show("Test");
});
我遇到的问题是它执行 _updateAvailable = await _updateManager.SearchForUpdatesAsync();
然后它不会继续线程,它只是停止,就好像调用之后什么都没有一样。 Visual Studio 过了一会儿也告诉我这个:Thread ... exited with code 259
,所以好像有东西还活着。
我调试它以搜索任何可能被吞噬的异常,但没有,一切正常,它执行 return-语句。
这就是我不明白的地方,我从来没有看到 MessageBox and/or 没有执行超出这一行的代码。
在我和一些朋友交谈后,他们确认这不应该。我在实现 async-await 时犯了一个可怕的错误吗?
提前致谢,实际上我只能说这么多,我没有更多信息,我非常感谢任何可能的提示和帮助。
最好的做法是在你的层中一直异步,然后调用 await 或更少 .Wait() / .Result 在最终使用地点。
此外,尽量将您的 UI 调用与后端工作分开,因为您可以 运行 处理 synchronicity/thread-context 问题。
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;
}
}
您遇到的主要问题是您在 TaskEx.Run()
中不必要地包装了您的方法,并且您可能在某处遇到了死锁。
您的方法签名当前为:
public async Task<bool> SearchForUpdatesAsync()
意思如下:
async
--> Doesn't actually do anything, but provides a "heads up" that await
might be called within this method and that this method can be used as a runnable Task.
Task
--> This method returns a runnable task that can be run asynchronously on the threadpool
<bool>
--> This method actually returns bool when awaited.
await TaskEx.Run()
是不必要的,因为它说 运行 这个方法,然后在值可用之前不要 return。这很可能导致同步问题。删除此构造将使您的方法正常工作,但您会注意到现在您甚至没有理由包含 async
运算符或 Task<T>
部分,因为该方法实际上是同步的。通常,如果您有要对它们调用 await
的方法,您只会在方法签名上使用 async
标识符。
相反,您有两个选择。
- 每当你想调用
SearchForUpdates()
时,你都可以将其包装在 Task<bool>.Run()
到 运行 异步(或 Bcl 等价物)
- 由于您使用的是 WinForms,因此最好使用
BackgroundWorker
并在其中调用此方法。
关于使用异步等待模式,我认为这是一篇很棒的文章,可以用来确保您遵循最佳实践:https://msdn.microsoft.com/en-us/magazine/jj991977.aspx
我有以下内容:
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。 现在在我的另一个 class 中,我用正常的 void:
写了这段代码TaskEx.Run(async delegate
{
// ...
_updateAvailable = await _updateManager.SearchForUpdatesAsync();
MessageBox.Show("Test");
});
我遇到的问题是它执行 _updateAvailable = await _updateManager.SearchForUpdatesAsync();
然后它不会继续线程,它只是停止,就好像调用之后什么都没有一样。 Visual Studio 过了一会儿也告诉我这个:Thread ... exited with code 259
,所以好像有东西还活着。
我调试它以搜索任何可能被吞噬的异常,但没有,一切正常,它执行 return-语句。 这就是我不明白的地方,我从来没有看到 MessageBox and/or 没有执行超出这一行的代码。 在我和一些朋友交谈后,他们确认这不应该。我在实现 async-await 时犯了一个可怕的错误吗?
提前致谢,实际上我只能说这么多,我没有更多信息,我非常感谢任何可能的提示和帮助。
最好的做法是在你的层中一直异步,然后调用 await 或更少 .Wait() / .Result 在最终使用地点。
此外,尽量将您的 UI 调用与后端工作分开,因为您可以 运行 处理 synchronicity/thread-context 问题。
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;
}
}
您遇到的主要问题是您在 TaskEx.Run()
中不必要地包装了您的方法,并且您可能在某处遇到了死锁。
您的方法签名当前为:
public async Task<bool> SearchForUpdatesAsync()
意思如下:
async
--> Doesn't actually do anything, but provides a "heads up" thatawait
might be called within this method and that this method can be used as a runnable Task.
Task
--> This method returns a runnable task that can be run asynchronously on the threadpool
<bool>
--> This method actually returns bool when awaited.
await TaskEx.Run()
是不必要的,因为它说 运行 这个方法,然后在值可用之前不要 return。这很可能导致同步问题。删除此构造将使您的方法正常工作,但您会注意到现在您甚至没有理由包含 async
运算符或 Task<T>
部分,因为该方法实际上是同步的。通常,如果您有要对它们调用 await
的方法,您只会在方法签名上使用 async
标识符。
相反,您有两个选择。
- 每当你想调用
SearchForUpdates()
时,你都可以将其包装在Task<bool>.Run()
到 运行 异步(或 Bcl 等价物) - 由于您使用的是 WinForms,因此最好使用
BackgroundWorker
并在其中调用此方法。
关于使用异步等待模式,我认为这是一篇很棒的文章,可以用来确保您遵循最佳实践:https://msdn.microsoft.com/en-us/magazine/jj991977.aspx