从后台任务中读取文件

时间:2014-07-31 10:26:32

标签: c# background task async-await

我正在尝试从后台任务的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();
    }

2 个答案:

答案 0 :(得分:0)

我假设通过死锁你的意思是反序列化方法结束太晚而你的原始程序在完成加载之前尝试读取数据。

这取决于您希望解决方案的复杂性/可靠性以及您打算如何使用该计划。最简单的方法依赖于目录创建功能在Windows / Unix和OSX中始终是100%原子的。例如,在readFile函数的顶部有这样的东西。

Directory.CreateDirectory("lock");

在开始在TileUpdater中解析异步操作的结果之前,请设置一个如下所示的循环。

while (Directory.Exists("lock"))
{
    Thread.Sleep(50);
}

这假设一切都发生在同一目录中,通常你会想要用一条路径替换“lock”,该路径指向用户的Windows / Linux / OSX版本的临时目录。

如果你想要从一系列文件中读取更复杂的东西,同时将反序列化的输出读入你的类,你将需要使用像System.Collections.Concurrent.ConcurrentQueue这样的东西。允许您的线程完全独​​立地执行而不会相互阻塞。

顺便说一下,我假设您知道类Process和.waitfor()存在。你可以分离一个线程,然后在稍后一点,停止主线程,直到产生的线程结束。

答案 1 :(得分:0)

其实我觉得我已经找到了问题所在。在名称空间中,我尝试过尝试并捕获,并且我在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。有什么想法吗?