2012-06-14 27 views
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()

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

你能检查我是否在代码中丢失了某些东西。

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

回答

8

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

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

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

+0

是的,我知道...... .net 4.5带来异步并等待关键字语言。但我的应用程序固有地被预Windows 8操作系统使用。 – Uday0119

+2

@ Uday0119:.NET 4.5并不局限于Windows 8. –

+0

现在我得到一个异常,因为“调用线程无法访问此对象,因为另一个线程拥有它。”从ContinueWith方法访问TextBlock方法 – Uday0119

1

我想应该是这样的

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

还是你只是在发布松动呢?您可能必须使用正确的调度程序,除此之外,这应该可以做到这一点

+0

现在我得到一个异常',因为不同的线程拥有it.'从ContinueWith方法访问TextBlock的 – Uday0119

+0

检查超负荷工作调用线程不能访问该对象继续使用(Func <任务,TNewResult> continuationFunction,TaskScheduler调度程序);你可以传递UI调度器,你可以使用var uithread = TaskScheduler.FromCurrentSynchronizationContext(); – Dominik

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#

相关问题