我正在尝试编写一个函数来从Windows 8商店应用程序的漫游文件夹中加载一些数据。
我在Load方法中的roamingLoad.Wait()上遇到死锁(挂起);
这样做的正确方法是什么?下面做错了什么?
编辑:我应该指出,如果我在调试器中执行它,它可以很好地工作。
如果没有顶级方法变得异步,有没有办法做到这一点?如果我这样做,那么每个调用方法必须说等待阻塞直到它没有完成?
public override bool Load(string in_FileNameAndDirectory, StreamTask in_StreamTask, bool in_PreferRoaming)
{
if (PreferRoaming && SupportsRoamingSave)
{
try
{
Task<bool> roamingLoad = RoamingLoadAsync(in_FileNameAndDirectory, in_StreamTask);
roamingLoad.Wait();
return roamingLoad.Result;
}
catch (Exception error)
{
return false;
}
}
return Load(in_FileNameAndDirectory, in_StreamTask);
}
private async Task<bool> RoamingLoadAsync(string inFileNameAndDirectory, StreamTask inStreamTask)
{
try
{
StorageFolder roamingFolder = ApplicationData.Current.RoamingFolder;
StorageFile sampleFile = await roamingFolder.GetFileAsync(inFileNameAndDirectory);
using (Stream stream = await sampleFile.OpenStreamForReadAsync())
inStreamTask(stream);
}
catch (Exception error)
{
return false;
}
return true;
}
答案 0 :(得分:1)
这样做的正确方法是什么?
你正在遇到common deadlock problem(我在博客上完整解释)。总而言之,您不应在异步任务上使用Task.Wait
或Task<T>.Result
。相反,您应该使用await
。
要使用await
,您的方法必须为async
。这意味着此签名与异步操作基本上不兼容:
public override bool Load(string in_FileNameAndDirectory, StreamTask in_StreamTask, bool in_PreferRoaming)
假设bool
结果实际上很重要(这肯定是有争议的 - 返回bool
结果而不是例外是80年代,你不会说吗?),正确的编写方法是更改基类签名,以便它支持异步操作:
public override async Task<bool> LoadAsync(string in_FileNameAndDirectory, StreamTask in_StreamTask, bool in_PreferRoaming)
{
if (PreferRoaming && SupportsRoamingSave)
{
try
{
return await RoamingLoadAsync(in_FileNameAndDirectory, in_StreamTask);
}
catch (Exception error)
{
return false;
}
}
return Load(in_FileNameAndDirectory, in_StreamTask);
}