【问题标题】:One Task throws AggregateException on multiple call一个任务在多次调用时抛出 AggregateException
【发布时间】:2013-05-27 03:24:26
【问题描述】:

我的问题是,当用户单击按钮时,会调用 SpeicherUser()。它通过异步使用 XMLSerialization 创建一个 xml 文件。所以当用户点击非常快并且一直在按钮上时,任务会被一遍又一遍地调用,如果没有完成(创建新的 xml 文件),就会弹出 AggregateException。

这是代码:

public class UserList
{
    private static List<User> _personen = new List<User>();
    public List<User> Personen
    {
        get { return _personen; }
        set { _personen = value; }
    }

    public static StorageFile file { get; set; }

    private const string filename = "Personen.xml";

    public UserList()
    {
        md.Title = "Fehler beim Speichern";
        Personen = new List<User>()
        {
            new User(){ID = 1, 
                Name = "TestUser1"},
            new User(){ID = 2, 
                Name = "TestUser2"}
        };
    }

    public async Task SpeicherUser()
    {
            await Save<UserList>();
    }

    static async public Task Save<T>()
    {
        if (await DoesFileExistAsync(filename))
        {
            //AggregatException pops up here: UserList.SaveAsync<T>().Wait()
            await Windows.System.Threading.ThreadPool.RunAsync((sender) => UserList.SaveAsync<T>().Wait(), Windows.System.Threading.WorkItemPriority.Normal);
        }
        else
        {
            file = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
        }
    }

    static async Task<bool> DoesFileExistAsync(string fileName)
    {
        try
        {
            await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
            return true;
        }
        catch
        {
            return false;
        }
    }

    static async private Task SaveAsync<T>()
    {
        StorageFile sessionFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
        IRandomAccessStream sessionRandomAccess = await sessionFile.OpenAsync(FileAccessMode.ReadWrite);
        IOutputStream sessionOutputStream = sessionRandomAccess.GetOutputStreamAt(0);
        var serializer = new XmlSerializer(typeof(List<User>), new Type[] { typeof(T) });

        //Using XmlSerializer
        serializer.Serialize(sessionOutputStream.AsStreamForWrite(), _personen);
        sessionRandomAccess.Dispose();
        await sessionOutputStream.FlushAsync();
        sessionOutputStream.Dispose();
    }
}

UserList 显示在 ListView 中。我现在有 1 个按钮,所以当用户单击该按钮时,一个新的“用户”将被添加到 ListView 中,并在它之后创建 XML 文件。为了解决我的问题,我可以使用 2 个按钮做一个 wordkaround: - 一种用于将用户添加到 ListView - 只有当用户创建新用户时,才会启用另一个。因此 XML 文件将被保存并且该按钮将被禁用。 但这不是真正的解决方案……就像我说的,这只是一种解决方法,并没有真正解决问题。

问题:我如何处理 static async public Task Save&lt;T&gt;() 的 AggregateException,上面写着“发生了一个或多个错误”。 -> 访问被拒绝(HRESULT 异常:0x80070005 (EACCESSDENIED)

【问题讨论】:

    标签: c# exception windows-8 task async-await


    【解决方案1】:

    异步编程确实迫使您设计您的 UI 有点不同。在这种情况下,您的 UI 有一个附加状态,即 正在创建用户

    处理这些短暂状态的一种常见方法是在操作进行时禁用按钮,例如:

    async void AddButton_Click(..)
    {
      addButton.IsEnabled = false;
      await Save();
      AddToListView();
      addButton.IsEnabled = true;
    }
    

    或者,您可以捕获异常并忽略它(因为这可能意味着已经有一个Add 正在进行中)。

    【讨论】:

    • 我不确定忽略异常是否是个好主意,因为它可能是一个真正的问题。
    • 好点。 “访问被拒绝”太宽泛了,无法假设它是一个已经打开的句柄。
    • 好吧,这实际上更容易。不知道为什么我想出了 2 个按钮,当我也可以启用/禁用一个按钮时......这不是关于如何处理异常的答案,但它是一个解决方案,所以我将它算作一个回答。
    猜你喜欢
    • 1970-01-01
    • 2016-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    相关资源
    最近更新 更多