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

时间:2012-04-30 11:51:44

标签: .net vb.net task-parallel-library nonblocking

我正在尝试等待.NET 4中的Task结果,就像在.NET 4.5中使用await关键字一样。我只是无法弄清楚如何做到这一点......

我的代码(以证明我至少要尝试):

    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

正如您所料,GetResponse调用在不同的线程上执行,但该函数必须等待结果才能返回。不幸的是,这阻止了我的主线程,直到任务完成,我没有丝毫的线索如何使它等待而不阻塞。我不想使用Async CTP,因为那只是逃避问题。

秘诀是什么?

1 个答案:

答案 0 :(得分:3)

没有秘密酱。如果你想创建一个返回某个异步操作结果的方法,你只需要阻塞该操作,直到操作完成。

但还有其他方法可以实现同样的目标。在.Net中执行此操作的“旧”方式与WebRequest使用相同:有两种方法BeginGetXDocumentEndGetXDocument。然后,您可以将委托传递给将在操作完成时执行的Begin方法。

另一种方法是从您的方法返回Task。为此,您可以使用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

这样,方法的使用者可以选择同步等待结果(使用Wait()Result),或者可以再次使用ContinueWith()

在GUI应用程序中使用ContinueWith()时,必须小心:默认情况下,继续在ThreadPool线程上运行。要在GUI线程上运行继续,可以使用TaskScheduler.FromCurrentSynchronizationContext()。或者特定于GUI库的方法(WPF中为Dispatcher.Invoke(),Winforms中为Control.Invoke()