【问题标题】:Async method only works when MessageDialog is called异步方法仅在调用 MessageDialog 时有效
【发布时间】:2018-05-22 16:35:14
【问题描述】:

我对 C# 非常陌生,但仍在尝试了解异步方法的工作原理。我的 UWP 应用需要在将压缩文件夹拖放到屏​​幕上时从压缩文件夹中检索 JPG 缩略图,在文件夹上传时显示带有进度环的缩略图,然后在上传完成后移除进度环。

首先当用户删除文件时触发此方法:

private async void OnFileDrop(object sender, DragEventArgs e)
{
    if (e.DataView.Contains(StandardDataFormats.StorageItems))
    {
        var items = await e.DataView.GetStorageItemsAsync();
        if (items.Count > 0)
        {

                foreach (var appFile in items.OfType<StorageFile>())
                {

                    StorageFolder downloadFolder = ApplicationData.Current.LocalFolder;

                    StorageFolder unzipFolder =
                await downloadFolder.CreateFolderAsync(Path.GetFileNameWithoutExtension(appFile.Name),
                CreationCollisionOption.GenerateUniqueName);

                    await UnZipFileAsync(appFile, unzipFolder);

                }
        }
    }

下一步:

public static IAsyncAction UnZipFileAsync(StorageFile zipFile, StorageFolder destinationFolder, Action<ZipArchiveEntry, StorageFolder> callback, Action<ZipArchiveEntry> completeCallback)
    {
        return UnZipFileHelper(zipFile, destinationFolder, thumbnailCallback, completeCallback).AsAsyncAction();
    }

然后此任务解压缩文件,在创建 ZipArchive 后调用 thumbnailCallback 方法:

 private static async Task UnZipFileHelper(StorageFile zipFile, StorageFolder destinationFolder, Action<ZipArchiveEntry, StorageFolder> thumbnailCallback, Action<ZipArchiveEntry> completeCallback)
    {
        if (zipFile == null || destinationFolder == null ||
            !Path.GetExtension(zipFile.Name).Equals(".zip", StringComparison.OrdinalIgnoreCase)
            )
        {
            throw new ArgumentException("Invalid argument...");
        }

        Stream zipMemoryStream = await zipFile.OpenStreamForReadAsync();

        // Create zip archive to access compressed files in memory stream
        using (ZipArchive zipArchive = new ZipArchive(zipMemoryStream, ZipArchiveMode.Read))
        {
            ZipArchiveEntry thumbnail = zipArchive.GetEntry("thumbnail.jpg");

            thumbnailCallback(thumbnail, destinationFolder);

            // Unzip compressed file iteratively.
            foreach (ZipArchiveEntry entry in zipArchive.Entries)
            {
                await UnzipZipArchiveEntryAsync(entry, entry.FullName, destinationFolder);

            }
        }
    }

这是 thumbnailCallback 方法,应该在上传文件夹时显示缩略图:

public async void thumbnailCallback(ZipArchiveEntry thumbnail, StorageFolder destinationFolder)
{
        // thumbnail only displays after this has been called and user clicks OK button to close dialog
        var messageDialog = new MessageDialog("displaying thumbnail");
        await messageDialog.ShowAsync();

        // code to display thumbnail

        Canvas canvas = new Canvas();
        canvas.Width = 200;
        canvas.Height = 125;
        ProgressRing progressRing = new ProgressRing();
        progressRing.Name = thumbnail.FullName;
        progressRing.IsActive = true;
        progressRing.Height = 50;
        progressRing.Width = 50;
        Canvas.SetTop(progressRing, 35);
        Canvas.SetLeft(progressRing, 75);
        Canvas.SetZIndex(progressRing, 2);

        Image thumb = new Image();
        thumb.Name = thumbnail.FullName;
        thumb.Width = 200;
        thumb.Height = 125;
        thumb.Opacity = 0.2;

        BitmapImage bitmapImage = new BitmapImage();
        Uri uri = new Uri(destinationFolder.Path + "\\" + thumbnail.FullName);
        bitmapImage.UriSource = uri;
        thumb.Source = bitmapImage;

        canvas.Children.Add(thumb);
        canvas.Children.Add(progressRing);




    }

目前缩略图仅在首先调用 MessageDialog.ShowAsync() 时才会显示,并且在单击对话框上的 OK 按钮之前不会显示。

【问题讨论】:

  • 如果显示缩略图的代码在await 之后,那么您看到的行为是预期的。在调用ShowAsync之前移动代码以显示缩略图。
  • 我明白,问题是我根本不希望 MessageDialog 出现,但如果我删除它,其余代码将不起作用。
  • 如果您删除消息对话框,程序是否结束?
  • @jdweng 不,它会继续上传文件夹,只是上传时不显示缩略图。
  • 现在您的原始代码无法编译,所以很难说,UnZipFileHelper 使用的参数数量不匹配。您可以完全从thumbnailCallback 中删除asyncShowDialogAsync。如果这不起作用,我们需要查看用于显示缩略图的代码。

标签: c# uwp async-await


【解决方案1】:

thumbnailCallback 在没有await 的情况下被调用。这就是不显示缩略图的原因(如果幸运的话,您可能会随机获得缩略图:))。当您放置 MessageDialog 时,线程有足够的时间在用户交互后执行。

如何修复

如下调用:

await thumbnailCallback(thumbnail, destinationFolder);

建议:

把签名改成

public async Task thumbnailCallback(ZipArchiveEntry thumbnail, StorageFolder destinationFolder)

通常,您希望返回 Task。主要的例外应该是当您需要有一个 void 返回类型(用于事件)时。

返回 void 的async 方法在另一方面是特殊的:它们代表顶级的 async 操作,并且当您的任务返回 exception 时,它们会发挥作用。

【讨论】:

  • 我收到以下错误:Task MainPage.thumbnailCallback(ZipArchiveEntry, StorageFolder)' has wrong return type
  • 我添加了return语句,现在出现这个错误:由于'MainPage.thumbnailCallback(ZipArchiveEntry,StorageFolder)'是一个返回'Task'的异步方法,return关键字后面不能跟一个对象表达式。您是否打算返回“Task”?
  • 你在方法thumbnailCallback中有任何等待的任务吗?
  • 当我把它改成 'Task' 时,我得到了这个:'Task' 是一种类型,在给定的上下文中是无效的
  • 不,没有
猜你喜欢
  • 1970-01-01
  • 2020-12-19
  • 1970-01-01
  • 2021-01-27
  • 1970-01-01
  • 2014-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多