c# – 为什么文件异步API阻塞
我正在写一个简单的城域应用程序.但是,访问文件时API会阻塞.通过阻止,我的意思是程序永远等待.创建/打开文件或文件夹最多需要几秒钟.在这种情况下,它需要永远.
当我运行程序时,它永远不会从OnTest返回.这是你得到的. 我的问题是: >你得到相同的行为(永远阻止程序) 这是XAML代码: <Button Click="OnTest">Test</Button> 这是C#代码: private async void OnTest(object sender,RoutedEventArgs e) { var t = new Cache("test1"); t = new Cache("test2"); t = new Cache("test3"); } class Cache { public Cache(string name) { TestRetrieve(name).Wait(); } public static async Task TestRetrieve(string name) { StorageFolder rootFolder = ApplicationData.Current.LocalFolder; var _folder = await rootFolder.CreateFolderAsync(name,CreationCollisionOption.OpenIfExists); var file = await _folder.CreateFileAsync("test.xml",CreationCollisionOption.OpenIfExists); } } 它阻止第二次调用新的Cache(“test2”); 解决方法
我没有试图运行你的程序或重现你的问题,但我可以做出有根据的猜测.
假设您自己写了以下待办事项列表: >在邮箱里给妈妈写一封信. 现在严格按照从上到下的顺序执行该列表中的所有操作.怎么了? 问题不在于邮局或妈妈;他们拿起你放在邮箱里的信,把它发给妈妈,妈妈正在写她的回复,邮局正把它寄回给你.问题是你永远不会进入第四步,因为你只能在完成第五步后启动第四步并且警报唤醒你.你会永远地睡觉,因为你基本上在等待未来的自我唤醒现在的自我.
别客气.
好吧,让我们分解吧.你的计划到底做了什么?让我们简化一下: void M() { Task tx = GetATask(); tx.Wait(); } async Task GetATask() { Task ty = DoFileSystemThingAsync(); await ty; DoSomethingElse(); } 首先:什么是任务?任务是一个对象,它代表(1)要完成的工作,以及(2)任务继续的委托:任务完成后需要发生的事情. 所以你打电话给GetATask.它有什么作用?嗯,它做的第一件事是它制作一个任务并将其存储在ty中.该任务表示作业“在磁盘上启动某些操作,并在完成后通知I / O完成线程”. 这项任务的延续是什么?完成任务后会发生什么?需要调用DoSomethingElse.因此,编译器将await转换为一堆代码,告诉任务确保在任务完成时调用DoSomethingElse. 在设置了I / O任务的延续的那一刻,方法GetATask将一个任务返回给调用者.那是什么任务?这与存储到ty中的任务不同.返回的任务是表示作业执行GetATask方法需要执行的所有操作的任务. 这项任务的延续是什么?我们不知道!这取决于GetATask的调用者. 好的,让我们回顾一下.我们有两个任务对象.一个代表任务“在文件系统上做这件事”.它将在文件系统完成其工作时完成.它的延续是“致电DoSomething”.我们有第二个任务对象代表作业“在GetATask的主体中做所有事情”.它将在调用DoSomethingElse返回后完成. 再说一遍:当文件I / O成功时,第一个任务将完成.当发生这种情况时,文件I / O完成线程将向主线程发送一条消息,说“嘿,你正在等待的文件I / O已经完成.我告诉你这个,因为现在是时候给你调用DoSomethingElse了”. 但是主线程没有检查它的消息队列.为什么不?因为你告诉它同步等待GetATask中的所有东西,包括DoSomethingElse,都完成了.但是现在无法处理告诉您运行DoSomethingElse的消息,因为您正在等待DoSomethingElse完成. 现在清楚了吗?你告诉你的线程要等到你的线程完成运行DoSomethingElse,然后再检查“请调用DoSomethingElse”是否在这个线程的工作队列中!你等到你读了妈妈的来信,但是你正在等待同步的事实意味着你没有检查你的邮箱,看看这封信是否已经到达. 在这种情况下,呼叫等待显然是错误的,因为您正在等待自己在将来做某事,而这不会起作用.但更一般地说,调用Wait完全否定了首先出现异步的整个问题.就是不要那样做;同时说“我想要异步”和“但我想同步等待”没有任何意义.那些是对立的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |