我使用下面的代码下载/保存图像并稍后打开它,但是在以后的OpenAsync中,它会抛出UnauthorizedAccessException,似乎文件没有关闭,但实际上IRandomAccessStream / DataWriter已被处理掉了。
HttpClient httpClient = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://www.silverlightshow.net/Storage/Users/nikolayraychev/Perspective_Transforms_4.gif");
HttpResponseMessage response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
//Write Image File
StorageFile imageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("test.gif", CreationCollisionOption.ReplaceExisting);
using (IRandomAccessStream fs = await imageFile.OpenAsync(FileAccessMode.ReadWrite))
{
using (DataWriter writer = new DataWriter(fs.GetOutputStreamAt(0)))
{
writer.WriteBytes(await response.Content.ReadAsByteArrayAsync());
await writer.StoreAsync();
writer.DetachStream();
await fs.FlushAsync();
}
}
StorageFile imageFile1 = await ApplicationData.Current.LocalFolder.GetFileAsync("test.gif");
//Exception is throwed here
using (IRandomAccessStream stream = await imageFile1.OpenAsync(FileAccessMode.Read))
{
BitmapImage img = new BitmapImage();
img.SetSource(stream);
}
答案 0 :(得分:6)
我遇到了同样的问题,在完成之前必须明确地处理流和文件对象。
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, Windows.Storage.CreationCollisionOption.ReplaceExisting);
using (var fs = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
{
var outStream = fs.GetOutputStreamAt(0);
var dataWriter = new Windows.Storage.Streams.DataWriter(outStream);
dataWriter.WriteString("Hello from Test!");
await dataWriter.StoreAsync();
dataWriter.DetachStream();
await outStream.FlushAsync();
outStream.Dispose(); //
fs.Dispose();
}
答案 1 :(得分:0)
使用'await'时不能“使用”。原因是编译器如何将C#await / async转换为IL。您可以反编译以查看它。
当处理器到达时:
await writer.StoreAsync();
实际上它会立即返回给调用者(参见IL)。由于您正在使用“using”,因此调用`IRandomAccessStream fs的Dispose
接口并释放资源。 “StoreAsync”中启动的线程需要这些资源。
出于这个原因,您必须在等待之后明确地调用Dispose
。
try / exception / catch块中出现同样的问题。
答案 2 :(得分:0)
在我看来,你正在泄漏传递给
的信息流 using (DataWriter writer = new DataWriter(fs.GetOutputStreamAt(0)))
如果流是引用计数的(毕竟它是winRT),那么传递给构造函数的临时对象将保持引用,并由DataWriter中的构造函数递增。
临时对象将等待垃圾回收。
如果您这样做,它是否有效:
using (var st0 = fs.GetOutputStreamAt(0))
using (DataWriter writer = new DataWriter(st0))