为什么文件异步API块 [英] Why does the file async API block

查看:140
本文介绍了为什么文件异步API块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写一个简单的地铁应用程序。但是,访问文件时的API块。通过阻止,我指的是节目将永远等待。创建/打开文件或文件夹应采取至多几秒钟。在这种情况下,它永远

I am writing a simple metro app. However, the API blocks when accessing files. By blocking, I mean the programs waits forever. Creating/opening a file or folder should take at most a few seconds. In this case, it takes forever.

当我运行程序,它从来没有来自OnTest回来。难道你会得到什么。
我明白.Wait将等待创建文件和文件夹finishe的。也许这不是伟大的设计。然而,这不是问题的关键。

When I run the program, it never comes back from OnTest. Is it what you get. I understand .Wait will wait for the creation of files and folders to finishe. Maybe that's not great design. However, that's not the point.

我的问题是:


  • 请你得到相同的行为(块程序永远)

  • 难道是什么应该发生的或者是在WinRT中的错误吗? (我用的是消费preVIEW)

  • 如果这是预期的行为,为何要采取永远?

下面是XAML code:

Here is the XAML code:

<Button Click="OnTest">Test</Button>

下面是C#code:

 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);
            }
        }

这是第二次调用新的高速缓存(测试2),它会阻止;

It blocks on the second call to new Cache("test2");

推荐答案

我还没有尝试运行您的程序或重现你的问题,但我可以做一个受过教育的猜测,到底是怎么回事。

I have not attempted to run your program or reproduce your problem, but I can make an educated guess as to what is going on.

假设你自己写下面的待办事项列表:

Suppose you wrote yourself the following to-do list:


  • 把一封信给妈妈的邮箱。

  • 设置报警尽快叫醒我,因为我读过她的回答。

  • 去睡觉。

  • 检查邮箱的答复。

  • 读取回复。

现在做的名单上的一切都严格按照从顶部到底部。会发生什么?

Now do everything on that list strictly in order from top to bottom. What happens?

问题是不是与邮局或母亲;他们拿起你把邮箱的信件,发送到妈妈,妈妈正在写她的​​回答和邮局把它回给你。问题是,你永远不会得到第四步,因为你只能开始后的第四步的你完成的第五的步骤和警报唤醒你。你会永远睡,因为的你基本上是等待你的未来的自己来唤醒你的present自我了的。

The problem is not with the post office or with mom; they are picking up the letter you put in the mailbox, sending it to mom, mom is writing her reply and the post office is bringing it back to you. The problem is that you never get to the fourth step because you only can start the fourth step after you complete the fifth step and the alarm wakes you up. You'll sleep forever because you are essentially waiting for your future self to wake your present self up.

埃里克,谢谢你的解释。

Eric, Thank you for the explanation.

不客气。

不过,我仍然困惑,为什么我的code不起作用。

However, I am still confused as to why my code does not work.

好吧,让我们打破它。什么是您的程序的真正的呢?让我们简化:

OK, let's break it down. What does your program really do? Let's simplify:

void M()
{
    Task tx = GetATask();
    tx.Wait();
}
async Task GetATask()
{
    Task ty = DoFileSystemThingAsync();
    await ty;
    DoSomethingElse();
}

第一关:什么的任务?任务是重​​新presents(1)做工作的对象,和(2)代表到的继续的任务:需要发生的事情后的 的任务就完成了。

First off: what is a task? A task is an object that represents (1) a job to be done, and (2) a delegate to the continuation of the task: the thing that needs to happen after the task is done.

所以,你叫GetATask。它有什么作用?那么,它的第一件事就是它使一个任务并将其存储在TY。这项任务重presents工作启动磁盘上的部分操作,当它完成通知I / O完成线程。

So you call GetATask. What does it do? Well, the first thing it does is it makes a Task and stores it in ty. That task represents the job "start some operation on the disk, and notify the I/O completion thread when it is done".

什么是的继续的那个任务吗?有什么要发生之后的任务是的完成的? DoSomethingElse需要被调用。所以编译器变换的的await 的成一束code,它告诉了任务,以确保当任务完成DoSomethingElse被调用。

What is the continuation of that task? What has to happen after that task is done? DoSomethingElse needs to be called. So the compiler transforms the await into a bunch of code that tells the task to ensure that DoSomethingElse is called when the task is done.

这在I / O任务的延续已被设定的时刻,方法GetATask 的返回给调用者的任务。的什么任务是什么?的这是一个的不同的的任务比得到存入TY任务。返回的任务是重新presents工作的尽一切GetATask需要的方法做的任务。

The moment that the continuation of the I/O task has been set, the method GetATask returns a task to the caller. What task is that? This is a different task than the task that got stored into ty. The task that is returned is the task that represents the job do everything that the method GetATask needs to do.

什么是任务的延续?我们不知道!即达的 GetATask的来电的决定。

What is the continuation of that task? We don't know! That is up to the caller of GetATask to decide.

好了,让我们回顾一下。我们有两个任务的对象。一重presents任务去做文件系统上的这件事情。该文件系统工作时,它会做。它的延续,是呼DoSomething的。我们有第二个任务对象重新presents在职GetATask的身体做的一切。它会做的之后调用DoSomethingElse返回

OK, so let's review. We have two task objects. One represents the task "go do this thing on the file system". It will be done when the file system does its work. It's continuation is "call DoSomething". We have a second task object that represents the job "do everything in the body of GetATask". It will be done after the call to DoSomethingElse returns.

还是那句话:第一个任务将是的完成后的文件I / O成功的。当发生这种情况时,文件I / O完成线程将消息发送到主线程说:哎,I / O,你在等待该文件已经完成。我告诉你,这是因为它现在是时候让你打电话DoSomethingElse

Again: the first task will be complete when the file I/O succeeds. When that happens, the file I/O completion thread will send a message to the main thread saying "hey, that file I/O you were waiting for is done. I am telling you this because it is now time for you to call DoSomethingElse".

不过,主线程的不检查它的消息队列的。为什么不?因为你告诉它同步等到一切都在GetATask,包括DoSomethingElse,完成。但是的的消息的就是告诉你的到现在运行DoSomethingElse 的无法处理的,因为你在等待DoSomethingElse是完整的

But the main thread is not examining its message queue. Why not? Because you told it to synchronously wait until everything in GetATask, including DoSomethingElse, is complete. But the message that is telling you to run DoSomethingElse now cannot be processed because you are waiting for DoSomethingElse to be complete.

现在是明确?你告诉你的线程等待,直到你的线程完成之前运行DoSomethingElse 您检查,看看是否请叫DoSomethingElse是要在这个线程执行的工作队列!你等着,直到你的从妈妈读信的,但是的您同步等待的事实意味着,你不检查你的邮箱,看看这封信已经到来的。

Now is it clear? You are telling your thread to wait until your thread is done running DoSomethingElse before you check to see if "please call DoSomethingElse" is in the queue of work to be performed on this thread! You are waiting until you have read the letter from mom, but the fact that you are waiting synchronously means that you are not checking your mailbox to see if the letter has arrived.

调用wait在这种情况下,显然是错误的,因为你在等待的自己做的东西在未来的,而不是去上班。但更普遍,称等待完全否定是异步的摆在首位,整个点。只是不要做;它没有任何意义,既说我想成为异步和,但我想同步等待。这些都是对立的。

Calling Wait is obviously wrong in this case because you are waiting for yourself to do something in the future, and that's not going to work. But more generally, calling Wait completely negates the entire point of being async in the first place. Just don't do that; it doesn't make any sense to say both "I want to be asynchronous" and "but I want to synchronously wait". Those are opposites.

这篇关于为什么文件异步API块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆