异步发送主线程信号

时间:2013-01-02 21:08:08

标签: c# multithreading

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

我尝试调用Invoke(从我的主窗体)调用委托来执行显示工作,但这会阻止我的下载程序线程直到完成。我有点想在没有EndInvoke的情况下做一个BeginInvoke,但我知道这样做不合适。

2 个答案:

答案 0 :(得分:6)

有几个选择。

我个人最喜欢的是使用TPL。在您的UI线程中,您可以创建TaskFactory,如下所示:

// Given:
// TaskFactory uiFactory;

uiFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());

然后,在后台任务中,您只需创建一个Task来更新您的用户界面:

var task = uiFactory.StartNew( () => UpdateUserInterface(data));

这将正确编组UI线程,类似于BeginInvoke调用。如果您需要阻止,可以调用task.Wait()(如果Update方法返回值,则调用task.Result

答案 1 :(得分: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()延续是合适的。