简体   繁体   English

.NET 4中的非阻塞Task.wait?

[英]Non-blocking Task.wait in .NET 4?

I'm trying to wait for a Task result in .NET 4, much like you can by using the await keyword in .NET 4.5. 我正在尝试等待.NET 4中的Task结果,就像您可以在.NET 4.5中使用await关键字一样。 I just can't figure out how to do it though... 我只是不知道该怎么做...

My code (to prove that I'm atleast trying): 我的代码(以证明我至少在尝试):

    Private Function GetXDocumentFromWebLocationAsync(ByVal request As WebRequest) As XDocument
        Dim queryTask As Task(Of WebResponse)
        queryTask = task(Of WebResponse).Factory.FromAsync(AddressOf request.BeginGetResponse, AddressOf request.EndGetResponse, Nothing, Nothing)
        Return XDocument.Load(queryTask.Result.GetResponseStream)
    End Function

As you would expect, the GetResponse calls are executed on a different thread, but the function has to wait for the result before it can return. 如您所料,GetResponse调用在另一个线程上执行,但是该函数必须等待结果才能返回。 Unfortunately this blocks my main thread until the task has completed and I don't have the slightest clue on how to make it wait without blocking. 不幸的是,这阻塞了我的主线程,直到任务完成为止,而且我对如何使其等待而不阻塞没有任何线索。 I don't want to use the Async CTP either because that's just running away from the problem. 我也不想使用异步CTP,因为这只是在解决问题。

What's the secret sauce? 秘诀是什么?

There is no secret sauce. 没有秘密的调味料。 If you want to make a method that returns with the result of some asynchronous operation, you simply have to block the thread until the operation completes. 如果要使方法返回某些异步操作的结果,则只需阻塞线程,直到操作完成即可。

But there are other ways to achieve the same thing. 但是还有其他方法可以实现相同的目的。 The “old” way of doing this in .Net is the same WebRequest uses: have two methods BeginGetXDocument and EndGetXDocument . .Net中执行此操作的“旧”方法与WebRequest使用的相同:具有两个方法BeginGetXDocumentEndGetXDocument You can then pass a delegate to the Begin method that will get executed when the operation completes. 然后,您可以将委托传递给Begin方法,该方法将在操作完成时执行。

Another way of doing this is to return a Task from your method. 执行此操作的另一种方法是从您的方法中返回一个Task To do that, you can use ContinueWith() : 为此,您可以使用ContinueWith()

Private Function GetXDocumentFromWebLocationAsync(ByVal request As WebRequest) As Task(Of XDocument)
    Dim queryTask As Task(Of WebResponse)
    queryTask = Task(Of WebResponse).Factory.FromAsync(
        AddressOf request.BeginGetResponse, AddressOf request.EndGetResponse, Nothing, Nothing)
    Return queryTask.ContinueWith(
        Function(antecendent) XDocument.Load(antecendent.Result.GetResponseStream))
End Function

This way, the consumer of the method can choose to wait for the result synchronously (using Wait() or Result ), or it can use ContinueWith() again. 这样,方法的使用者可以选择同步Wait()结果(使用Wait()Result ),也可以再次使用ContinueWith()

When using ContinueWith() in GUI applications, you have to be careful: the continuation is run on a ThreadPool thread by default. 在GUI应用程序中使用ContinueWith()时,必须小心:默认情况下,延续在ThreadPool线程上运行。 To run your continuation on the GUI thread, you can use TaskScheduler.FromCurrentSynchronizationContext() . 要在GUI线程上运行继续,可以使用TaskScheduler.FromCurrentSynchronizationContext() Or a method specific for your GUI library ( Dispatcher.Invoke() in WPF, Control.Invoke() in Winforms). 或特定于您的GUI库的方法Dispatcher.Invoke() WPF中为Dispatcher.Invoke() Control.Invoke() ,Winforms中为Control.Invoke() )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM