Prevent user interface hangs without additional threads

What solutions do I have if I want the user interface to not hang when I deserialize a large number of user interface elements in WPF? I get errors complaining that objects belong to a user interface thread when I try to load them into another thread. So, what parameters do I need to prevent so that the "Program Error" error does not respond when I load my user interface data? Can I rely on a single-threaded solution, or am I missing something in relation to, possibly, multiple user interface threads?

+5
source share
7 answers

If you use only one thread, then the user interface will freeze while you perform any processing.

If you use the BackgroundWorker stream, you will have more control over what happens and when.

To update the user interface, you need to use Dispatcher.Invokefrom your background thread to march the call along the stream boundary.

Dispatcher.Invoke(DispatcherPriority.Background,
                  new Action(() => this.TextBlock.Text = "Processing");
+11
source

Here is a great blog post by Dwane Need that discusses all the available options for working with user interface elements among several threads.

, . , , , ? , . , , ?

+2

DispatcherFrames, .

. , , , . . , ,

, , , , :

  • DispatcherFrame
  • BeginInvoke, Continue = false
  • PushFrame ,

, , Dispatcher.BeginInvoke ..

:

  public partial class MyWindow
  {
    SomeDeserializer _deserializer = new SomeDeserializer();

    byte[] _sourceData;
    object _deserializedObject;

    ...

    void LoadButton_Click(...)
    {
      Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
      {
        _deserializedObject = _deserializer.DeserializeObject(_sourceData);
      }));
    }
  }

  public class OneOfTheObjectsBeingDeserializedFrequently
  {
    ...

    public string SomePropertyThatIsFrequentlySet
    {
      get { ... }
      set { ...; BackgroundThreadingSolution.DoEvents(); }
    }
  }

  public class BackgroundThreadingSolution
  {
    [ThreadLocal]
    static DateTime _nextDispatchTime;

    public static void DoEvents()
    {
      // Limit dispatcher queue running to once every 200ms
      var now = DateTime.Now;
      if(now < _nextDispatchTime) return;
      _nextDispatchTime = now.AddMilliseconds(200);

      // Run the dispatcher for everything over background priority
      var frame = new DispatcherFrame();
      Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
      {
        frame.Continue = false;
      }));
      Dispatcher.PushFrame(frame);
    }
  }

DateTime.Now DoEvents() , , , SomeProperty .

: , , , DoEvents. DispatcherFrame Dispatcher.Invoke :

    public static void DoEvents()
    {
      // Limit dispatcher queue running to once every 200ms
      var now = DateTime.Now;
      if(now < _nextDispatchTime) return;
      _nextDispatchTime = now.AddMilliseconds(200);

      // Run the dispatcher for everything over background priority
      Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new Action(() => {}));
    }
+2

, . , DispatcherTimer Loaded. , DispatcherPriority.Input.

+1

, , Dispatcher.BeginInvoke(your_UI_action_here)

0

OldNewThing.

, , GUI , , . , .

So One GUI Thread .

- , , , . , , , " " .

0

UIElements. , InvalidOperationException, , .

. , - , , - , .

0