为什么 MS 强迫我进行异步操作?

Why is MS forcing me into an asynchronous operation?

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

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

但是,我看不出有什么方法可以同步进行。 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("");
    }
}

这让我发疯。

人们写道 Async 应该被拥抱、拥抱和欣赏,但就我而言,它只会带来麻烦。

我看不出有什么方法可以使这个东西同步,我想知道为什么 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;
        }
    }

当您说您的应用程序无法在没有数据库的情况下工作时,请记住使用 await 关键字就可以做到这一点,因此下面的代码行在异步调用 returns 之后才会执行。您可以构建您的代码,使其在您等待数据库重新联机时响应。

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

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

或者,更好的是,看看 JoinableTaskFactory

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

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

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

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

您所要做的就是:

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

然后就可以等待了:

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

这一切都会在你打电话之前完成 return (_dbApp = new DB(path));

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