1

我有一个从电子邮件标题中提取值的函数。为了加快速度,想使用框架 4.5 中的异步。这是我第一次尝试使用异步。

我连续多次异步调用提取函数以提取不同的值。来自电子邮件标题。我遇到的麻烦是如何知道所有实例何时完成。我找到了一些例子,但没有一个适合我的条件任务。

我相信我需要:

  • 调暗任务数组
  • 将每个必要的任务添加到数组中
  • 之后,使用 Task.WhenAll

但是,我不知道该怎么做。

            'Extract these vars from header if no value was passed
            'Calling HeaderExtract Async for speed
            If Len(sClient) = 0 Then
                sClient = HeaderExtractAsync("Client,", sHeaders).Result
   ' --> Add this as a new task?
            End If
            If Len(sSubscriptionNum) = 0 Then
                sSubscriptionNum = HeaderExtractAsync("SubscriptionNum,", sHeaders).Result
            End If
            If Len(sTargetID) = 0 Then
                sTargetID = HeaderExtractAsync("TargetID,", sHeaders).Result
            End If
            If Len(sAddressBook) = 0 Then
                sAddressBook = HeaderExtractAsync("AddressBook,", strHeaders).Result
            End If

' --> Check that all are done?
4

2 回答 2

1

出色地。您似乎正在使用异步编程,但您根本没有使用它,首先我建议您在这里阅读:http: //blogs.msdn.com/b/windowsappdev/archive/2012/04/24/diving -deep-with-winrt-and-await.aspx和这里:http: //blogs.msdn.com/b/windowsappdev/archive/2012/06/14/exposing-net-tasks-as-winrt-asynchronous-operations .aspx,这些资源适用于 WinRT,但您可能会得到图片。

现在,您的方法返回 a Task<TResult>(这很好),但是通过调用Result您实际上是同步的,因为 Result 总是在返回某些内容之前等待 Task 结束。使这个异步的方法是这样的:

If Len(sClient) = 0 Then
    Dim tClient as Task(Of Whatever) = HeaderExtractAsync("Client,", sHeaders)
    tClient.Start()
End If

然后稍后检查任务是否已完成,如下所示:

If tClient.IsCompleted Then
    DoSomething()
Else
    ContinueWaiting();
End If

可能你可能想把它放在一个循环中,这样你就可以确定如果任务没有完成你等到它完成。

编辑:

我意识到您似乎想将任务用作线程,即使您可以这样做,但任务并不适合此目的,任务更多地用于触发可能需要一段时间才能完成的活动,然后当它完成时将控件完全返回到调用函数的位置,而不会阻塞主线程(通常是 UI 线程),考虑到这一点,您也可以在此处阅读:http: //blogs.msdn.com/b /benwilli/archive/2013/04/24/tasks-are-not-threads.aspx,这是一个关于如何正确使用任务的示例,假设HeaderExtractAsync需要一段时间才能完成:

If Len(sClient) = 0 Then
    sClient  = Await HeaderExtractAsync("Client,", sHeaders)
End If
于 2013-06-14T19:03:43.817 回答
1

首先,HeaderExtract运行需要多长时间,启动异步任务的开销非常大,如果HeaderExtract快速返回,您可能会使程序变慢。

第二,您没有获得等待的任何好处,您需要调用Await Foo()它以将控制权交还给消息泵,Foo().Result这将停止您的程序并使您的 UI 无响应(如果这是在 ui 线程上)

最后,如果确实需要一段时间才能完成您想要启动所有任务然后检查结果,否则您将等待第一个结果返回,然后再开始寻找第二个结果。

'Extract these vars from header if no value was passed
'start off all the tasks before we start checking for results
If Len(sClient) = 0 Then
    tClient = HeaderExtractAsync("Client,", sHeaders)
End If
If Len(sSubscriptionNum) = 0 Then
    tSubscriptionNum = HeaderExtractAsync("SubscriptionNum,", sHeaders)
End If
If Len(sTargetID) = 0 Then
    tTargetID = HeaderExtractAsync("TargetID,", sHeaders)
End If
If Len(sAddressBook) = 0 Then
    tAddressBook = HeaderExtractAsync("AddressBook,", strHeaders)
End If

'now start waiting for results
If tClient IsNot Nothing
    sClient = Await tClient
If tSubscriptionNum IsNot Nothing
    sSubscriptionNum = Await tSubscriptionNum
If tTargetID IsNot Nothing
    sTargetID = Await tTargetID
If tAddressBook IsNot Nothing
    sClsAddressBookient = Await tAddressBook

如果您宁愿让线程休眠而不是等待(例如您没有使用 .NET 4.5,并且您只是在 OP 中使用了错误的标签),请将这些sFoo = await tFoo行替换为sFoo = tFoo.Result

于 2013-06-14T23:23:30.997 回答