我有一个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提前
答案 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});
或者你在张贴期间放松了吗?您可能必须使用正确的调度程序,除此之外,这应该可以解决问题