简体   繁体   English

异步方法仅在调用MessageDialog时有效

[英]Async method only works when MessageDialog is called

I am very new to C# and still trying to understand how async methods work. 我是C#的新手,仍然尝试了解异步方法的工作原理。 My UWP app needs to retrieve a thumbnail JPG from a compressed folder when it is dropped onto the screen, display the thumbnail with a progress ring while the folder is uploading, and then remove the progress ring when upload is complete. 我的UWP应用程序放到屏幕上时,需要从压缩的文件夹中检索缩略图JPG,在文件夹上传时显示带有进度环的缩略图,然后在上传完成后删除进度环。

First this method is triggered when the user drops a file: 首先,当用户删除文件时触发此方法:

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);

                }
        }
    }

Next: 下一个:

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

Then this Task unzips the file, calling the thumbnailCallback method after the ZipArchive has been created: 然后,此任务将文件解压缩,并在创建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);

            }
        }
    }

This is the thumbnailCallback method which is supposed to display the thumbnail while the folder is being uploaded: 这是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);




    }

Right now the thumbnail will only display if MessageDialog.ShowAsync() is called first, and it does not appear until the OK button has been clicked on the dialog box. 现在,仅在首先调用MessageDialog.ShowAsync()时才会显示缩略图,并且只有在对话框中单击“确定”按钮后,缩略图才会出现。

thumbnailCallback is called without await . 在没有await情况下调用thumbnailCallback That's the reason thumnail are not not displayed (if you are lucky you may get thumbnail randomly :)). 这就是未显示缩略图的原因(如果幸运的话,您可能会随机获得缩略图:))。 When you put MessageDialog then thread is enough time to execute after user interaction. 当您放置MessageDialog时,线程有足够的时间在用户交互之后执行。

How to Fix 怎么修

Call it like as below: 如下调用:

await thumbnailCallback(thumbnail, destinationFolder);

Suggestion : 建议:

Change the signature as 将签名更改为

public async Task thumbnailCallback(ZipArchiveEntry thumbnail, StorageFolder destinationFolder)

Normally, you would want to return a Task . 通常,您需要返回Task The main exception should be when you need to have a void return type (for events). 主要的例外应该是当您需要具有void返回类型(用于事件)时。

async methods that return void are special in another aspect: they represent top-level async operations, and have additional rules that come into play when your task returns an exception . 返回void的async方法在另一方面是很特殊的:它们代表顶级async操作,并且在任务返回exception时会起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM