【问题标题】:Asynchronous call to WriteAsync, how do i know when it’s complete?异步调用 WriteAsync,我怎么知道它何时完成?
【发布时间】:2014-02-14 05:19:26
【问题描述】:

我正在使用异步调用将文件写入到 IsolatedStorageFile

async void  Base64ToImage()
{
   byte[] data;
   using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
   {
     using (IsolatedStorageFileStream isfs = isf.OpenFile("image.p64", FileMode.Open, FileAccess.ReadWrite))
      {
         data = new byte[isfs.Length];
         isfs.Read(data, 0, data.Length);
         isfs.Close();
      }

     using (IsolatedStorageFileStream stream = isf.OpenFile("newReConvertedFile.png", FileMode.Create))
     {
         await stream.WriteAsync(data, 0, data.Length);

 ///////////////////The problem is here, how would i know when WriteAsync is complete to then fire the reload method?
        //reLoadFile();
      }
   }
}

我需要知道 WriteAsync 何时完成才能以另一种方法重新加载该文件,我该怎么做?

编辑:

实际上我的第一个想法是将文件保存到 isostorage,然后将图像 uri 发送到该文件,但是您不能将 uri 设置为图像的 isostorage,或者至少我无法显示

我最初的想法是等待方法调用以重新加载文件,但我得到一个错误“???不返回任务,不能等待。考虑将其更改为返回”,但我不知道该怎么做。

这里的想法是将几个图像转换为 Base64 (SQLite db),然后只加载选定的图像以显示。

reLoadFile方法如下

async void reLoadFile()
{
    byte[] newFile;
    using (IsolatedStorageFile newFileLoc = IsolatedStorageFile.GetUserStoreForApplication())
    {
        using (IsolatedStorageFileStream newFileStream = newFileLoc.OpenFile("newReConvertedFile.png", FileMode.Open, FileAccess.ReadWrite))
        {
            newFile = new byte[newFileStream.Length];
            newFileStream.Read(newFile, 0, newFile.Length);
            newFileStream.Close();

            var ms = new MemoryStream(newFile); 
            var image = new BitmapImage(); 
            image.SetSource(ms); 
            theImage.Source = image; 
        }
     }
 }

我一直在搜索帖子,但我找不到让它工作的好方法,因为如果我立即调用它,我会遇到异常。 我需要做的是打开文件将其从base64转换为.png,然后在保存后加载.png文件。 如果有人可以帮助我,我将不胜感激。

谢谢鲍勃。

【问题讨论】:

  • 我不明白为什么这个问题被否决了。它提供了回答问题所需的所有细节。
  • 您不应该使用 async void,将您的方法更改为 async Task
  • @vcsjones 我也不明白...

标签: c# visual-studio-2012 asynchronous windows-phone-8 async-await


【解决方案1】:

1) reloadFile 不需要是async 你只需要在方法中使用await 关键字时使用它

2) BaseTo64Image 需要声明为async Task Base64ToImage() 否则Base64ToImage() 的调用者将无法判断它何时完成。

3) isfs.Read(data, 0, data.Length); 不好,仅仅因为您请求了data.Length 字节并不意味着您将获得data.Length 读入,您需要检查int 读取返回并循环或使用CopyTo(Stream) 进行复制到另一个流。

4)(实际回答您的问题)关键字await 将停止处理函数并等待函数完成。当您点击 await 关键字时,您的 Base64ToImage() 函数将在此时返回一个 Task 代表该函数中的其余代码,这取决于您如何处理从函数返回的 Task .

这是使用所有建议的代码的简化版本

async Task Base64ToImage()
{
    using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
    using (IsolatedStorageFileStream stream = isf.OpenFile("newReConvertedFile.png", FileMode.Create))
    using (IsolatedStorageFileStream isfs = isf.OpenFile("image.p64", FileMode.Open, FileAccess.ReadWrite))
    {
         await isfs.CopyToAsync(stream);
    }      

    await ReLoadFile();
}

async Task ReLoadFile()
{


    using (IsolatedStorageFile newFileLoc = IsolatedStorageFile.GetUserStoreForApplication())
    {
        using (IsolatedStorageFileStream newFileStream = newFileLoc.OpenFile("newReConvertedFile.png", FileMode.Open, FileAccess.ReadWrite))
        {
            var ms = new MemoryStream();
            var image = new BitmapImage();
            await newFileStream.CopyToAsync(ms);

            ms.Position = 0;    
            image.SetSource(ms); 
            theImage.Source = image; 
        }
     }
 }

但是,如果这就是您所做的全部,并且您只是使用 newReConvertedFile.png 作为临时文件,您可以将代码简化为

async Task Base64ToImage()
{
    using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
    using (IsolatedStorageFileStream isfs = isf.OpenFile("image.p64", FileMode.Open, FileAccess.ReadWrite))
    {
         var ms = new MemoryStream();
         var image = new BitmapImage();
         await isfs.CopyToAsync(ms);

         ms.Position = 0;
         image.SetSource(ms); 
         theImage.Source = image; 
    }      
}

【讨论】:

  • 我不确定我是否理解你,也许你可以给我举个例子?
  • 在 ReloadFile 调用中我在这里遇到错误: var ms = new MemoryStream(newFileStream.Length);关于你进一步简化的建议,我试图保存它以供参考它应该应用墓碑,你怎么看?
  • 如果您不告诉我错误是什么以及为什么要保存它,我真的无法帮助您解决错误,您正在制作一个文件的副本,然后什么都不做第二次阅读。除非您有被排除的代码。
  • 错误Argument 1: cannot convert from 'long' to 'byte[]' 我仍在处理它,图像将存储在 SQLite db(base64 格式)中,然后根据需要拉出,我正在保存临时文件,以便有一个参考应用停用的情况。
  • 我没有意识到 Length 正在返回一个 Long 只是使用无参数构造函数。
【解决方案2】:

WriteAsync 方法在其返回的Task 完成时完成。

要等待任务完成,只需await它:

await stream.WriteAsync(data, 0, data.Length);
// WriteAsync is complete.

【讨论】:

    【解决方案3】:

    只需在下一行调用它。 await 将异步等待,直到 WriteAsync 完成。这就是“async/await”的美妙之处,它可以让您编写看起来同步的异步代码。

     using (IsolatedStorageFileStream stream = isf.OpenFile("newReConvertedFile.png", FileMode.Create))
     {
         await stream.WriteAsync(data, 0, data.Length);
         reLoadFile();
      }
    

    我错过了什么吗?

    【讨论】:

    • 我试过了,但我得到了一个例外,我认为该文件可能仍然没有保存或当时仍在访问?
    • @BobMachine 只需将 reLoadFile 调用移到 using 语句后并检查。那应该可以解决您的问题
    • 将它移到使用之外,这绝对是问题的一部分,谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-08
    • 2017-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多