3

在我的应用程序(Windows 8 Metro)中,我将一些对象以序列化格式存储在本地文件夹中。这是读取然后返回的方法(见下文)。

如果我用 Task.Run 调用这个方法,我可以得到对象:

var entity= Task.Run<Entity>(() => GetASync<Entity>(file)).Result;

但是如果我使用 await 关键字,它就不起作用 - 在方法中的行 A (ReadObject) 上,线程停止并退出,没有错误或异常:

var entity= await GetASync<Entity>(file);

也许我没有像推荐的那样使用 await / async ?

方法

private async Task<T> GetASync<T>(IStorageFile file) where T : class
{
    try
    {    
        if (file != null)
        {
            IRandomAccessStream readStream = await file.OpenAsync(FileAccessMode.Read);
            IInputStream inputStream = readStream.GetInputStreamAt(0);                   
            using (XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(inputStream.AsStream(), XmlDictionaryReaderQuotas.Max))
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(T));
                var entity = serializer.ReadObject(reader); //line A - here the problem 
                return entity as T;
            }                    
        }
        else
        {
            return null;
        }

    }
    catch (FileNotFoundException)
    {
        return null;
    }
    catch (Exception)
    {
        throw;
    }
}
4

2 回答 2

3

好吧,我不知道为什么你的代码不起作用。我怀疑是死锁,但应该有。:)

但是,我确实有一些性能建议可能会避免该问题作为副作用。首先是使用ConfigureAwait(false)

IRandomAccessStream readStream = await file.OpenAsync(FileAccessMode.Read)
                                           .StartAsTask()
                                           .ConfigureAwait(false);

另一种是将文件读入内存(异步)然后解析。(我从您的代码中假设您为每个文件存储一个对象)。

于 2011-12-19T04:05:26.960 回答
1

从http://social.msdn.microsoft.com/Forums/en-US/async/thread/3f192a81-073a-47ea-92e2-5ce02bf5ad33回复:

您遇到了 Microsoft 在 BUILD 会议上分发的 .NET 开发人员预览版中的一个已知问题。该问题是由 WinRT UI 线程的一些细微细节引起的。因此,如果从 UI 线程执行,任何来自托管代码的阻塞 WinRT 流 IO 都将导致死锁。异步 IO(例如ReadAsync)可以正常工作。开发团队已经意识到这个问题并正在努力解决它。

但是请注意,即使问题得到解决,在 UI 线程上执行阻塞 IO 也不是一个好主意。您的应用程序将在操作期间阻塞并且无响应。一些 .NET API(还)没有异步等效项,即使有,转换代码也可能需要工作。如果必须执行阻塞 IO 操作,请确保将其卸载到线程池:

DoUIStuff();
Int32 x = await Task.Run(() => {
    OpenStream();
    PerformBlockingIO();
    ProcessResults();
    return ComputeIOResults();
});
UseIOResults(x);

这样,您就可以始终保持应用程序响应。作为副作用,您还将解决上述错误并避免死锁。

于 2011-12-21T07:51:28.763 回答