C# 从后台任务读取文件
我试图从后台任务的Run方法内部调用一个方法,该方法需要序列化一个xml文件。问题是我最终陷入了僵局。这是读取文件的方法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
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等。有机会举个很小的例子吗?感谢你花了这么多时间,我很感激。