【问题标题】:FileIO.AppendTextAsync throwing random exceptions when used in a loopFileIO.AppendTextAsync 在循环中使用时抛出随机异常
【发布时间】:2013-06-12 22:53:58
【问题描述】:

所以我有一个特殊的问题。我有一组这样的方法:

StorageFile file;
public void WriteStuff() //This implements an interface, so can't be changed to async with a task returned
{
    Write();
}
async void Write()
{
  await FileIO.AppendTextAsync(file, DateTime.Now + " testing!"+Environment.NewLine);
}
async void Create()
{
  file=await ApplicationData.Current.LocalFolder.CreateFileAsync("test.txt", CreationCollisionOptions.OpenIfExists);
}

然后像这样实际使用它的代码:

var x=new Foo();
for(int i=0;i<1000;i++)
{
  x.WriteStuff(); //can't use async/await from here. This is in a portable class library
}

每当我打电话给Test 时,我都会收到非常随机的错误。诸如 FileNotFound、AccessDenied、AccessViolation 等。

它似乎只在异步调用AppendTextAsync 多次时发生。我会想象一个异步 API 会......好吧,线程安全,但显然不是。这是真的?

另外,如何在不修改调用代码的情况下解决此问题?

【问题讨论】:

  • 抱歉,您需要使用async Task
  • 异步与线程无关。异步 API 很少是线程安全的。

标签: c# .net windows-runtime windows-store-apps async-await


【解决方案1】:

如果你真的需要这样做,那么你唯一的选择就是同步Wait()让异步方法完成(或者使用Result):

void Write()
{
    FileIO.AppendTextAsync(
        file, DateTime.Now + " testing!"+Environment.NewLine).Wait();
}

void Create()
{
    file = ApplicationData.Current.LocalFolder.CreateFileAsync(
        "test.txt", CreationCollisionOptions.OpenIfExists).Result;
}

但这违背了异步代码的全部目的,所以你真的应该避免这样做。此外,如果您调用的代码没有正确编写,这样做会导致死锁。

不能从这里使用 async/await。这是在一个可移植的类库中

可以使用来自 PCL 的async-await。您只需定位支持它的平台,如果您的平台本身不支持它,还可能引用 Microsoft.Bcl.Async。

【讨论】:

  • @SLaks 就像我说的,它可能会死锁,这取决于调用的异步方法是如何实现的。 (如果他们在任何地方都使用ConfigureAwait(false),或者如果他们没有使用async-await 实现,则不会死锁,因此不要捕获当前上下文。)
猜你喜欢
  • 2011-01-16
  • 2014-03-16
  • 2016-06-09
  • 1970-01-01
  • 2014-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-17
相关资源
最近更新 更多