使用Async保存FileStream

时间:2017-06-29 11:36:47

标签: c# wpf async-await

我正在尝试将文件(BitmapImage)保存到某个位置,但只要我使用async& await我收到错误消息说文件正在使用中:

  

该进程无法访问文件'C:\ Users \ ... \ image1.jpg'因为   它被另一个进程使用。

我的编码:

BitmapImage image = new BitmapImage(new Uri(oldImagePath));
var encoder = new JpegBitmapEncoder() { QualityLevel = 17 };
encoder.Frames.Add(BitmapFrame.Create(image));

using (var filestream = new FileStream(GetImageLocation(), FileMode.Create))
    await Task.Run(() => encoder.Save(filestream)); //Error here

当我使用代码而不 await时,代码完全正常。我想这可能是因为另一个线程可能正在使用它,但任何人都可以帮助或向我解释我的问题吗?谢谢。

3 个答案:

答案 0 :(得分:6)

如果您使用Task await,则会使用另一个帖子保存您的encoder。但是您的编码器也被主线程使用,因此新线程无法使用它。

稍微更改您的代码:

await Task.Run(() => 
{ 
    using (var filestream = new FileStream(GetImageLocation(), FileMode.Create))
    {      
         BitmapImage image = new BitmapImage(new Uri(oldImagePath));
         var encoder = new JpegBitmapEncoder() { QualityLevel = 17 };
         encoder.Frames.Add(BitmapFrame.Create(image));
         encoder.Save(filestream);
    }
}

现在您在同一任务中创建并保存encoder,它只使用一个线程。

答案 1 :(得分:4)

我认为您应该将代码移到// Snip of other code $data = array( 'voornaam' => $_POST['voornaam'], 'achternaam' => $_POST['achternaam'], 'email' => $_POST['email'], 'wachtwoord' => ($_POST['wachtwoord']), 'startdatum' => date('Y-m-d'), 'postcode' => $_POST['postcode'], 'huisnummer' => $_POST['huisnummer'], 'woonplaats' => $_POST['woonplaats'], 'beschrijving' => $_POST['beschrijving'], 'geboortedatum' => $_POST['geboortedatum'], 'geslacht' => $_POST['geslacht'], 'profiel_foto' => $image ); $this->db->insert('users', $data); var_dump($data); exit(); // Snip of other code 中,因为它会在另一个线程中被调用。

答案 2 :(得分:3)

您可以编码为MemoryStream,获取字节数组,使用WriteAsync上的FileStream,并完全避免使用Task.Run

BitmapImage image = new BitmapImage(new Uri(oldImagePath));
var encoder = new JpegBitmapEncoder() { QualityLevel = 17 };
encoder.Frames.Add(BitmapFrame.Create(image));
using (var mem = new MemoryStream())
using (var filestream = new FileStream(GetImageLocation(), FileMode.Create))
{
    encoder.Save(mem);
    var data = mem.ToArray();
    await filestream.WriteAsync(date, 0, data.Length);
}

请注意,这会在编码期间阻塞您的线程并使用更多内存。