开发者

Multi-Threading WPF with Accessors

I am trying to update a UI element from a different thread but I am clearly missing something with regards to the new WPF calls.

In 3.5 winforms I did something like the following when updating my UI via a different thread:

    public string SummaryTitle
  {
   get
   {
    if (IsHandleCreated && InvokeRequired)
    {
     IAsyncResult result = BeginInvoke(new Func<object, object[], object>(GetType().GetProperty("SummaryTitle").GetValue), this, null);
     return EndInvoke(result).ToString();
    }

    return myTextBox.Text.Trim();
   }
   set
   {
    if (IsHandleCreated && InvokeRequired)
    {
     BeginInvoke(new Action<object, object, object[]>(GetType().GetProperty("SummaryTitle").SetValue), this, value, null);
    }
    e开发者_开发技巧lse
    {
     myTextBox.Text = value;
    }
   }
  }

Now with 4.0 WPF I am trying to simulate the above, but with the new Dispatcher (maybe there is a different/better way, besides dispatcher?). Here is the prototype code I am playing with now (I know there are nonthreading related issues still in it, please ignore that for now) and it is not working right:

     public string SomeText
  {
   get {
    if(!myTextBox.Dispatcher.CheckAccess())
    {
     object o = myTextBox.Dispatcher.Invoke(new Func<object, object[], object>(GetType().GetProperty("SomeText").GetValue), this, null);
     return o != null ? Convert.String(o) :  "";
    }

    return myTextBox.Text.Trim(); 
   }
   set
   {
    if (!myTextBox.Dispatcher.CheckAccess())
    {
     myTextBox.Dispatcher.Invoke(new Action<object, object, object[]>(GetType().GetProperty("SomeText").SetValue),this, value, null);
     return;
    } 

    myTextBox.Text = value;
   }
  }

Any help on how to make the WPF accessor function similar to the old 3.5 winforms method would be appreciated.


EDIT: I am looking more at a way to make an accessor on the UI for a screen element thread-safe than the thread caller or progressbar specifically. The accessor needs to be able to be executed from another assembly or class regardless of whether that calling class is using Thread or BackgroundWorker. Also, it needs to hold water for all UI elements, not just a progress bar. So that a textbox, etc. can also be make thread safe in this manner. I updated the examples to help better convey my troubles.


I'm still fairly new with WPF, but whenever I use the dispatcher I specify what priority level to run the action on. This determines when the action actually gets run

myControl.Dispatcher.BeginInvoke(DispatcherPriority.Render,
    new Action(delegate()
    {
        // Code to execute goes here
    }
));

A list of the PriorityLevels can be found here

It looks like you're trying to update a progress bar... If your bar is bound to something (say a number that is between 0 and 100) you could add the dispatcher call to your long-running process and have it update the number. DataBinding should take care of the rest.


I know that you are interested in getting Dispatcher to work properly, but for something like this, have you looked at using the BackgroundWorker? While a little limiting as far as priorities and such, it certainly simplifies running calculations on a background thread while updating the UI.

Here is a SO thread where I helped somebody use a BackgroundWorker.

Of course, if you are using some other threading model, this may not work for you - YMMV - but if you are simply interested in doing some work in the background while updating a ProgressBar, take a look.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜