简体   繁体   English

在后台线程WPF中创建UI?

[英]creating a UI in background thread WPF?

I tried following: 我试过以下:

var task = new Task(() =>
    {
       for (int i=0; i<10; i++) {
          //Create new Grid HERE
          // Add Table with some dynamic data here..
          // print the above Grid here.
        }

    });

task.ContinueWith((previousTask) =>
    {
        label.Content = printerStatus(); // will return "Out of Paper", "printing", "Paper jam", etc.
    },
    TaskScheduler.FromCurrentSynchronizationContext());

label.Content = "Sending to printer";

It returns following error: The calling thread must be STA, because many UI components require this.. 它返回以下错误:调用线程必须是STA,因为许多UI组件需要这个..

The error occurs when it tries to create a new UI object Grid. 尝试创建新的UI对象Grid时发生错误。

How can i fix this? 我怎样才能解决这个问题? Let me know if there is any other way arround! 如果还有其他任何方式让我知道!

Tasks use thread pool threads, which are in a MTA. 任务使用MTA中的线程池线程。

If you want a background STA thread, you will have to create one yourself and explicitly set the ApartmentState . 如果您需要后台STA线程,则必须自己创建一个并明确设置ApartmentState

Thread t = new Thread( ... );
t.SetApartmentState( ApartmentState.STA );
t.Start();

Using the Dispatcher for the label and Invoke might help: 使用Dispatcher作为标签和Invoke可能会有所帮助:

label.Dispatcher.Invoke(
      System.Windows.Threading.DispatcherPriority.Normal,
      new Action(
        delegate()
        {
          label.Content = printerStatus();
        }
    ));

You cannot create UI objects on different thread than the main UI thread because as soon as you add them to the UI, it tries to set the Parent property, and a thread in WPF cannot modify objects that were created on a different thread. 您不能在与主UI线程不同的线程上创建UI对象,因为只要将它们添加到UI,它就会尝试设置Parent属性,并且WPF中的线程无法修改在不同线程上创建的对象。

Instead, I'd recommend creating a list or collection of the Grid's Data on the 2nd thread, and binding it to the UI using something like an ItemsControl . 相反,我建议在第二个线程上创建Grid的数据列表或集合,并使用类似ItemsControl东西将其绑定到UI。 This will keep all UI objects on the main UI thread, while background processing can be done on a background thread. 这将使所有UI对象保留在主UI线程上,而后台处理可以在后台线程上完成。

To update a UI object from a background thread, such as your status label, I'd recommend using the Dispatcher like lawrencealan's answer suggests. 要从后台线程(例如状态标签)更新UI对象,我建议使用Dispatcherlawrencealan的回答所示。 The Dispatcher is WPF's internal message queue for the main UI thread Dispatcher是WPF的主UI线程的内部消息队列

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM