2013-01-02 119 views
1

我可能会对这一切都错,但我卡住了。我有一个GUI应用程序,它生成一个单独的线程,从服务器下载一堆数据。当这个下载线程完成后,我希望它向主线程发送一个信号,以便它知道它现在可以显示下载的数据。异步信号主线程

我已经打过电话调用(从我的主要形式)来调用一个委托做的工作显示,但这块我的下载线程,直到其完成。我有点想做一个没有EndInvoke的BeginInvoke,但我知道它不适合这样做。

+0

你可以张贴一些代码? Control.Invoke(委托)应该工作得很好 –

+0

BeginInvoke不需要EndInvoke。我始终在没有EndInvoke的情况下使用BeginInvoke。 – Casperah

+0

也检查http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx – MBen

回答

6

有几个选项。

我个人最喜欢的是使用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)。

+0

谢谢。这正是我一直在寻找的东西。必须传递一个'Control'的实例,所以你可以'一直调用'对我来说似乎是错误的。 –

+1

@FrankWeindel关于这一点的好处是它可以与任何UI框架一起工作,甚至可以与WCF的同步上下文一样使用。在使用TPL时,您不会绑定到特定的UI框架(WPF,Silverlight,WinForms等),而且它也很好地转换为C#5的异步。 –

0

有几种选择:

  • 对于的WinForms使用Control.BeginInvoke method
  • 对于WPF使用Dispatcher.BeginInvoke method
  • “的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()延续将是适当的。