使用Task执行异步操作但UI仍然没有响应

时间:2012-06-14 06:17:46

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

我有一个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()

但问题是即使我使用Task异步,UI仍然没有响应。

请你能检测我是否遗漏了代码中的内容。

任何帮助/建议都将受到高度赞赏 Thanx提前

3 个答案:

答案 0 :(得分:8)

启动任务后,您在线路上使用t.Result。这将使线程阻塞直到任务完成 - 所以所有的异步都是徒劳的。

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

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

答案 1 :(得分: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#

答案 2 :(得分:1)

我认为它应该像

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

或者你在张贴期间放松了吗?您可能必须使用正确的调度程序,除此之外,这应该可以解决问题