C# 从后台任务读取文件

C# 从后台任务读取文件,c#,background,task,async-await,C#,Background,Task,Async Await,我试图从后台任务的Run方法内部调用一个方法,该方法需要序列化一个xml文件。问题是我最终陷入了僵局。这是读取文件的方法 protected async Task<Anniversaries> readFile(string fileName) { IStorageFile file; Anniversaries tempAnniversaries; file = awai

我试图从后台任务的Run方法内部调用一个方法,该方法需要序列化一个xml文件。问题是我最终陷入了僵局。这是读取文件的方法

protected async Task<Anniversaries> readFile(string fileName)
    {                        
        IStorageFile file;
        Anniversaries tempAnniversaries;   

        file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);            
        using (IRandomAccessStream stream =
            await file.OpenAsync(FileAccessMode.Read))                
        using (Stream inputStream = stream.AsStreamForRead())
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(Anniversaries));
            tempAnniversaries = serializer.ReadObject(inputStream) as Anniversaries;
        }

        return tempAnniversaries;            
    } 
这里是Run方法

public sealed class TileUpdater : IBackgroundTask
{        
    GeneralAnniversariesManager generalManager = new GeneralAnniversariesManager();
    Anniversaries tempAnn = new Anniversaries();        
    string test = "skata";

    public async void Run(IBackgroundTaskInstance taskInstance)
    {  
        DateTime curentTime = new DateTime();         

     var defferal = taskInstance.GetDeferral();
     await generalManager.InitializeAnniversariesAsync().AsAsyncAction();
     curentTime = DateTime.Now;
     var updater = TileUpdateManager.CreateTileUpdaterForApplication();
     updater.EnableNotificationQueue(true);

     updater.Clear();

     for (int i = 1; i < 6; i++)
          {
           var tile = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150BlockAndText01);
           tile.GetElementsByTagName("text")[0].InnerText = test + i;
           tile.GetElementsByTagName("text")[1].InnerText = curentTime.ToString();

           updater.Update(new TileNotification(tile));
          }

            defferal.Complete();
    }

我假设死锁意味着反序列化方法完成得太晚,并且原始程序试图在数据加载完成之前读取数据

这取决于您希望您的解决方案有多复杂/可靠,以及您打算如何使用该程序。最简单的方法是,在Windows/Unix和OSX中,目录创建函数始终是100%原子的。例如,在readFile函数的顶部有如下内容

Directory.CreateDirectory("lock");
while (Directory.Exists("lock"))
{
    Thread.Sleep(50);
}
在TileUpdater中开始解析异步操作的结果之前,请创建一个如下所示的循环

Directory.CreateDirectory("lock");
while (Directory.Exists("lock"))
{
    Thread.Sleep(50);
}
这假设所有事情都发生在同一个目录中,通常您希望用一个路径替换lock,该路径指向用户的Windows/Linux/OSX版本的临时目录

如果要实现更复杂的功能,即在读取一系列文件的同时将反序列化输出读取到类中,则需要使用类似System.Collections.Concurrent.ConcurrentQueue的功能,该功能允许线程完全独立地执行操作,而不会相互阻塞


顺便提一下,我假设您知道类进程和函数.waitfor存在。您可以剥离一个线程,然后在稍后停止主线程,直到生成的线程完成。

实际上,我想我已经找到了问题所在。在名称空间方面,我尝试了try and catch,但在datacontract serealizer中使用不同的名称空间时出现了一个异常。我已经像这样更新了代码

            file = await ApplicationData.Current.LocalFolder.GetFileAsync("EortologioMovingEntries.xml");
        try
        {
            using (IRandomAccessStream stream =
            await file.OpenAsync(FileAccessMode.Read))
            using (Stream inputStream = stream.AsStreamForRead())
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(Anniversaries), "Anniversaries", "http://schemas.datacontract.org/2004/07/Eortologio.Model");
                tempAnniversaries = serializer.ReadObject(inputStream) as Anniversaries;
            }
        }
        catch (Exception ex)
        {
            error = ex.ToString();
            tempAnniversaries.Entries.Add(new AnniversaryEntry("Ena", DateTime.Now, "skata", PriorityEnum.High));                
        }

我现在没有得到任何异常,但是tempAnniversaries返回null。有什么想法吗?

您的第一个using语句没有包含代码的另一部分。您如何调用Run?Run是从后台任务调用的。什么是不包含,我在主应用程序中使用相同的代码,它可以工作。请原谅我的无知,我完全是新手。事实并非如此。我想在后台任务中用xml文件的内容填充一个列表,并在经过一些处理后在活动磁贴上显示结果。当我调用readfile任务时会发生死锁。没有涉及ui。正如我所说,同样的代码在主程序上运行良好。如果你愿意,我可以给你发一个项目的链接来测试它。当然,你能发一个链接吗?当然。再次非常感谢。我认为当我尝试将序列化程序分配给TempsNnVersary对象时,readFile方法中的AnniversaryManager类中出现了问题。暂时不要感谢我,它在我的Visual Studio版本中没有打开。编辑:过早按enter键。我想补充的是,async/await实际上并不会使您的程序成为多线程的,并且会导致这些类型的错误。这就是为什么我建议使用CreateDirectory/ConcurrentQueue和Process类,如果您真的希望自己的东西是多线程的。你一直在使用它们,没有经过你的代码,我不知道是哪一个导致了它,但我建议删除它们并实现另一种方法来确保数据一致性。我以前从未使用过createDirectory等。有机会举个很小的例子吗?感谢你花了这么多时间,我很感激。