我可能会对这一切都错,但我卡住了。我有一个GUI应用程序,它生成一个单独的线程,从服务器下载一堆数据。当这个下载线程完成后,我希望它向主线程发送一个信号,以便它知道它现在可以显示下载的数据。异步信号主线程
我已经打过电话调用(从我的主要形式)来调用一个委托做的工作显示,但这块我的下载线程,直到其完成。我有点想做一个没有EndInvoke的BeginInvoke,但我知道它不适合这样做。
我可能会对这一切都错,但我卡住了。我有一个GUI应用程序,它生成一个单独的线程,从服务器下载一堆数据。当这个下载线程完成后,我希望它向主线程发送一个信号,以便它知道它现在可以显示下载的数据。异步信号主线程
我已经打过电话调用(从我的主要形式)来调用一个委托做的工作显示,但这块我的下载线程,直到其完成。我有点想做一个没有EndInvoke的BeginInvoke,但我知道它不适合这样做。
有几个选项。
我个人最喜欢的是使用TPL。在您的UI线程,你可以做一个TaskFactory
,像这样:
// Given:
// TaskFactory uiFactory;
uiFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
然后,在你的后台任务,你可以创建一个Task
更新您的UI:
var task = uiFactory.StartNew(() => UpdateUserInterface(data));
这将元帅UI线程正确,类似于调用BeginInvoke
。如果需要阻止,则可以拨打task.Wait()
(如果Update方法返回值,则为task.Result
)。
谢谢。这正是我一直在寻找的东西。必须传递一个'Control'的实例,所以你可以'一直调用'对我来说似乎是错误的。 –
@FrankWeindel关于这一点的好处是它可以与任何UI框架一起工作,甚至可以与WCF的同步上下文一样使用。在使用TPL时,您不会绑定到特定的UI框架(WPF,Silverlight,WinForms等),而且它也很好地转换为C#5的异步。 –
有几种选择:
“的TPL有其他调度,除了默认的,还允许您创建自定义调度一种是基于当前同步上下文TPL提供调度器,它可以被用来确保我的任务在UI线程上执行“。 (Source article):
var ui = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.ContinueWhenAll(tasks.ToArray(),
result =>
{
var time = watch.ElapsedMilliseconds;
label1.Content += time.ToString();
}, CancellationToken.None, TaskContinuationOptions.None, ui);
与下载方案的情况下,.ContinueWith()
延续将是适当的。
你可以张贴一些代码? Control.Invoke(委托)应该工作得很好 –
BeginInvoke不需要EndInvoke。我始终在没有EndInvoke的情况下使用BeginInvoke。 – Casperah
也检查http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx – MBen