0

我有一个 WPF 应用程序,我必须在其中执行一项长时间运行的任务(基本上是从网络读取)。只是为了给你一个快照我在按钮点击时做以下事情

 Dim t As Task(Of String) = Task.Factory.StartNew(Of String)(Function()
                                                                        'Thread.sleep is simulating long running task that will make UI unresponsive
                                                                        Thread.Sleep(10000)
                                                                        Return "Hello world from async task"
                                                                    End Function)

        TextBlock1.Text = t.Result

我不能使用基于事件的异步方法,因为读取 API 实际上存在于我在我的程序中引用的 dll 中,其中包含一个函数Public function ReadFromNetwork() as String。此 API 正在对网络进行异步调用以读取长字符串并返回 UI。所以,简而言之,我在做TextBlock1.Text = ExternalDll.ReadFromNetwork()

但问题是即使我使用任务异步,用户界面仍然没有响应。

您能否检测一下我是否在代码中遗漏了某些内容。

任何帮助/建议将不胜感激 Thanx 提前

4

3 回答 3

8

你在t.Result开始任务后就行了。这将使线程阻塞,直到任务完成 - 所以所有的异步都是徒劳的。

您应该使用 附加一个延续Task.ContinueWith,并将使用任务结果的代码放入该延续中。这将允许 UI 在任务执行时返回处理事件,然后在任务完成时触发您的 continuation。传入TaskScheduler.FromCurrentSynchronizationContext以确保继续在正确的线程上触发。

请注意,在 VB/C# 的下一个版本中,所有这些都将使用异步方法变得更加容易如果您能够使用 .NET 4.5 候选版本,您应该考虑立即尝试 - 它会让您的生活变得更加简单。

于 2012-06-14T06:21:29.067 回答
2

您正在调用t.Result这将强制任务执行。您应该使用ContinueWith异步获取结果。

    var action = delegate(Task<string> s)  // to avoid cross thread exception 
        {
            Action ac = delegate() { TextBlock1.Text = s.Result; };
            this.Dispatcher.Invoke(ac);

        };

      t.ContinueWith(action);

请原谅我使用 c#

于 2012-06-14T06:27:51.500 回答
1

我认为应该是这样的

t.ContinueWith((result) => { TextBlock1.Text = result.Result});

还是你在发帖时把它弄松了?您可能必须使用正确的调度程序,除此之外这应该可以解决问题

于 2012-06-14T06:21:21.330 回答