-1

我需要从资源中的文本文件中读取数值(版本号)。我将此版本号与已安装组件的版本号进行比较。如果资源中的版本号高于安装的版本,我将新组件(数据库)从我的资源复制到用户可以使用的本地目录。

我需要同步执行此操作,因为我的应用程序在没有数据库的情况下无法工作。

但是,我看不到任何同步的方法。MS强迫我用这样的异步任务来做:

private async Task<string> ResourcesReadTextFile(string uFileName)
{
    string sRet = "";

    try
    {
        StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(cstAssets + uFileName));
        using (var inputStream = await file.OpenReadAsync())
        using (var classicStream = inputStream.AsStreamForRead())
        using (var streamReader = new StreamReader(classicStream))
        {
            while (streamReader.Peek() >= 0)
            {
                sRet = streamReader.ReadLine();
            }
        }
    }
    catch (Exception ex)
    {
        Debug.Assert(false);//check here
    }
    return sRet;
}

现在我遇到了应用程序在数据库复制到本地目录之前启动的情况,因为复制也需要异步完成,根本没有任何方法可以同步。没有像 StorageFile.Copy() 这样的函数。

因此,我使用的是:

private async void pCopyFromResourcesToLocal(string uFileName)
{
    // Cant await inside catch, but this works anyway
    try
    {
        StorageFile storfile = await StorageFile.GetFileFromApplicationUriAsync(new Uri(cstAssets + uFileName));
        await storfile.CopyAsync(ApplicationData.Current.LocalFolder);
    }
    catch (Exception ex)
    {
        Debug.WriteLine("");
    }
}

这让我发疯。

人们写道,应该拥抱、拥抱和欣赏异步,但在我的情况下,它只会带来麻烦。

我看不到任何使这件事同步的方法,我想知道为什么 MS 强迫我这样做。

非常感谢任何帮助。

谢谢你。

代码作为屏幕截图:

在此处输入图像描述

编辑:我在这里添加了顶级方法:

    public static async Task<DB> InitAppDb()
    {
        IFileHelper helper = DependencyService.Get<IFileHelper>();
        string path = await helper.GetFilePathAndCopyFromResourcesIfNotPresent("tablet.db");

        return (_dbApp = new DB(path));
    }

    public async Task CopyDatabaseIfNotExists(string uFileName)
    {
        IsolatedStorageFile nExpectedFolder = IsolatedStorageFile.GetUserStoreForApplication();
        bool bCopyNewDB = false;

        Task<bool> datatask = pResourceIsNewer(uFileName);
        bCopyNewDB = await datatask;

        if (! bCopyNewDB)
        {
            try
            {
                await ApplicationData.Current.LocalFolder.GetFileAsync(uFileName); //nExpectedFolder.GetFileAsync(dbPath);/// ApplicationData.Current.LocalFolder.GetFileAsync("preinstalledDB.db");
                // No exception means it exists
                return;
            }
            catch (System.IO.FileNotFoundException)
            {
                // The file obviously doesn't exist
            }
        }

        pCopyFromResourcesToLocal(uFileName);

    }

    private async Task<bool>pResourceIsNewer(string uPath)
    {
        string sFileNameAppDBVersion =uPath + ".txt";

        if (IsolatedStorageFileExist(sFileNameAppDBVersion))
        {
            int iAppDBVersionInstalled = Convert.ToInt32(IsolatedStorageReadTextFile(sFileNameAppDBVersion));

            Task<string> datatask = ResourcesReadTextFile(sFileNameAppDBVersion);
            string s = await datatask;

            int iAppDBResources = Convert.ToInt32(s);

            bool b = (iAppDBResources > iAppDBVersionInstalled);
            return b;
        }
        else
        {
            return true;
        }
    }
4

3 回答 3

5

你所要做的就是:

//private async void pCopyFromResourcesToLocal(string uFileName) { ... }
  private async Task pCopyFromResourcesToLocal(string uFileName) { ... }

然后你可以等待它:

//pCopyFromResourcesToLocal(uFileName);
  await pCopyFromResourcesToLocal(uFileName);

这一切都将在您致电之前完成return (_dbApp = new DB(path));

这个async/await链中的任何事情都不会发生乱序。

于 2017-11-24T15:32:43.863 回答
1

当您说您的应用程序在没有数据库的情况下无法运行时,请记住使用 await 关键字就是这样做的,因此在异步调用返回之前,以下代码行不会执行。您可以构建您的代码,使其在您等待数据库重新联机时响应。

但是,您可以使用以下构造强制您的函数同步:

StorageFile.GetFileFromApplicationUriAsync(new Uri(cstAssets + uFileName)).GetAwaiter().GetResult();

或者,更好的是,看看JoinableTaskFactory

于 2017-11-24T13:47:16.587 回答
-1

.GetAwaiter().GetResult()正如@pm_2 所说,任何异步API 方法都可以通过简单地在末尾标记来实现同步。

Task<T>结果的情况下,您可以简单地使用.Result, 和Task结果,.Wait()

您可以编写一个异步函数来读取您的文件,然后在顶层等待其结果,或者您可以编写一个同步方法并等待它对异步函数的每次调用的结果。

因此,Microsoft 并没有强迫您做任何事情:它只是提供了一个更简单的 API,它具有异步和同步工作流的最低公分母。

于 2017-11-24T14:22:54.690 回答