Package.Current.InstalledLocation.GetFileAsync和StorageFile.CopyAsync无法按预期工作

时间:2017-09-04 18:28:36

标签: c# sqlite uwp xamarin.forms

我需要"种子"我的应用程序与SQlite数据库。我在帖子How to deploy a database file with a Xamarin.form app?中使用了@Kasper建议的代码。

我的UWP代码看起来像这样。

public async Task<String> GetDBPathAndCreateIfNotExists()
    {
        String filename = "birdsnbflys.db3";
        bool isExisting = false;
        try
        {
            StorageFile storage = await ApplicationData.Current.LocalFolder.GetFileAsync(filename);
            isExisting = true;
        }
        catch (Exception)
        {
            isExisting = false;
        }
        if (!isExisting)
        {
            StorageFile databaseFile = await Package.Current.InstalledLocation.GetFileAsync(filename);
            await databaseFile.CopyAsync(ApplicationData.Current.LocalFolder, filename, NameCollisionOption.ReplaceExisting);

        }
        return Path.Combine(ApplicationData.Current.LocalFolder.Path, filename);
    }

当我在&#34;本地机器上运行时#34;它&#34;挂起/永不返回&#34;

StorageFile databaseFile = await Package.Current.InstalledLocation.GetFileAsync(filename);

如果我查看Package.Current.InstalledLocation文件夹,那么数据库文件就在那里。

当我在其中一个设备模拟器上运行它时,它会挂起/永远不会从&#34;

await databaseFile.CopyAsync(ApplicationData.Current.LocalFolder, filename, NameCollisionOption.ReplaceExisting);

在这种情况下,如果我退出应用程序然后重新启动它,该文件现在位于ApplicationData.Current.LocalFolder中,以便应用程序运行。

考虑到我的应用程序的需求,我会很高兴采用同步方式来做到这一点,但它看起来并不像微软提供任何东西而是异步。

有关如何按预期工作的任何想法或建议吗?

谢谢, 戴夫

2 个答案:

答案 0 :(得分:0)

首先,我建议您使用GetFileAsync而不是TryGetItemAsync。这样,您就可以避免使用try-catch块 此外,您应该在案例中使用ConfigureAwait(false)。您不需要该方法返回同一个线程。最终,您的问题是由死锁引起的。

// The caller of this method may use ConfigureAwait(false) as well,
// depending on the call-site and result-usage.
public async Task<String> GetDBPathAndCreateIfNotExists()
{
    String filename = "birdsnbflys.db3";

    // Check if file exists
    var file = await ApplicationData.Current.LocalFolder.TryGetItemAsync(filename).ConfigureAwait(false);
    var fileExists = file != null;

    // If the file doesn't exist, copy it without blocking the task
    if (!fileExists)
    {
        var databaseFile = await Package.Current.InstalledLocation
            .GetFileAsync(filename)
            .ConfigureAwait(false);
        await databaseFile.CopyAsync(ApplicationData.Current.LocalFolder,
                                     filename,
                                     NameCollisionOption.ReplaceExisting)
                          .ConfigureAwait(false);
    }

    return Path.Combine(ApplicationData.Current.LocalFolder.Path, filename);
}

答案 1 :(得分:0)

在阅读了关于async / await的大量内容并查看各种问题和答案之后,看起来我的问题是由错误地调用GetDBPathAndCreateIfNotExists方法引起的。这是在App类的属性中完成的。

我的初始代码是:

Task<string> bnbreproTask = DependencyService.Get<IFileHelper>().GetDBPathAndCreateIfNotExists();

我发现替代它可以消除这些问题:

var dbName = Task.Run(async () => { return await DependencyService.Get<IFileHelper>()
                    .GetDBPathAndCreateIfNotExists(); })
                    .Result;

我有足够的async / await经验,每次尝试使用它时都会遇到麻烦,所以我不知道这是不是最好的解决方案。它在这种情况下确实有效。

戴夫