2

我有一个函数,它从存储中打开一个文件并返回一个布尔值,指定文件打开得很好。

private async Task<bool> SaveImage()
{
    try
    {
        await filesave.openAsync(FileAccessMode.ReadWrite)
    }
    catch()
    {
        return false;
    }

    return true;
}

我想调用 await SaveImage() 函数,但不知何故想要一个侦听器/事件处理程序来告诉我何时完成。完成后我想用新数据更新我的布局。使用适用于 Windows 8 的新 WINRT async/await 异步方法如何实现这一点?是否有解决方法/替代方法。

如何设置事件处理程序类型场景?(完成)

4

3 回答 3

4

您只需await调用您的方法,然后在它完成后使用应该运行的代码。您不需要手动注册事件处理程序。

var succeeded = await SaveImage();
// Because of the "await" keyword in the above line, the current method
// will not continue until "SaveImage" has completed its async work and
// signaled its Task
if (succeeded) { ... }

当然,由于上面的代码使用了await关键字,所以需要将它放在一个也标记为 的方法中async。如果该方法需要向其调用者发出完成信号,那么它也应该返回一个Taskor Task<T>; 例如:

private async Task<string> MyHelperMethod() {
    var succeeded = await SaveImage();
    if (succeeded)
        return "Success";
    else
        return "Failure";
}
// then, in some other method:
    var message = await MyHelperMethod();

或者,如果调用的方法SaveImage是行尾——比如说它是 a 事件的处理程序Button——Click那么它可以是async void

private async void ButtonClick(object sender, EventArgs args) {
    var succeeded = await SaveImage();
    if (succeeded) { ... }
}
于 2012-08-06T03:52:14.610 回答
0

这需要更多的代码,但它是处理异步操作、进度、取消和完成状态的一种非常酷且有用的方法。这是在 VS2012 Winrt Store App 中编译的,我通过单击按钮运行它,如您在此处看到的。

    private void Save_File_Click(object sender, RoutedEventArgs e)
    {
        // create your op, bool = return type, string = progress report
        IAsyncOperationWithProgress<bool, string> op;

        // Call our async operation with progress sending the file name
        op = OpenFileWithProgress("test.txt");

        //  not implemented here
        //op.Cancel(); 

        // when we get a progress update...
        op.Progress = (info, progress) =>
        {
            // I'm just giving text feed back to user here
            Debug.WriteLine(progress);
        };
        op.Completed = (info, status) =>
        {
            // check status for completion or cancellation...
            switch (status)
            {
                case AsyncStatus.Completed:
                    //  Do your completed work here
                    Debug.WriteLine("Completed");
                    break;
                case AsyncStatus.Canceled:
                    // Operation canceled - not implemented...
                    Debug.WriteLine("Canceled");
                    break;
                default:
                    // default stuff here
                    break;
            }
        };
    }

    public IAsyncOperationWithProgress<bool, string> OpenFileWithProgress(string fileName)
    {
        return System.Runtime.InteropServices.WindowsRuntime.AsyncInfo.Run<bool, string>((token, progress) =>
            Task.Run<bool>(async () =>
            {
                progress.Report("Starting");
                try
                {
                    StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(fileName);
                }
                catch (Exception ex)
                {
                    return false;
                }

                progress.Report("Finished");

                return true;

            }, token));
    }
于 2012-12-05T15:30:09.637 回答
0

Joe 的回答看起来很棒,但如果您坚持使用事件 - 例如,如果您的 SaveImage() 调用位于与更新布局无关的各个代码区域 - 您可以在操作完成时引发事件。您可以使用普通的旧 CLR 事件或使用pub-sub 模式实现,例如 Prism 的EventAggregator或MVVM Light 的Messenger。POCE 版本可能如下所示

public event EventHandler<Tuple<StorageFile,bool>> SaveImageCompleted;

private async Task<bool> SaveImage(StorageFile file)
{
    try
    {
        await file.OpenAsync(FileAccessMode.ReadWrite);
    }
    catch
    {
        if (SaveImageCompleted != null)
            SaveImageCompleted(this, new Tuple<StorageFile, bool>(file, false));

        return false;
    }

    if (SaveImageCompleted != null)
        SaveImageCompleted(this, new Tuple<StorageFile, bool>(file, true));

    return true;
}
于 2012-08-06T05:51:17.903 回答