2013-01-02 63 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()延續將是適當的。