0

In the wpf application there is a canvas which i pass to my Game class. In my gameclass I want to update the canvas every 0.02 seconds. At the moment my code is working but it feels 'hacky', my code:

public void Start()
{

    bw = new BackgroundWorker();
    bw.DoWork += bw_DoWork;
    bw.ProgressChanged += bw_ProgressChanged;
    bw.WorkerReportsProgress = true;
    bw.RunWorkerAsync();
}

void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    GameRender();
}

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    while (Running)
    {
        GameUpdate();
        //GameRender();
        bw.ReportProgress(1);        
        //repaint();   
        try
        {
            Thread.Sleep(10);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex + "");
        }
    }
}

Because it seems like a hack to me I tried using a Thread like;

    public void Start()
    {

        new Thread(() =>
        {
            while (true)
            {
                GameUpdate();
                GameRender();
            }
        }).Start();
    }

But this crashes in my GameRender() where i try to update my canvas. Error:

An unhandled exception of type 'System.InvalidOperationException' occurred in WindowsBase.dll

How should I update the Canvas from a class?

Sven van den Boogaart
  • 11,833
  • 21
  • 86
  • 169
  • Its not in UI thread so it throws invalid operation. For UI operations try using Application.Current.Dispatcher.BeginInvoke( DispatcherPriority.Background, new Action(() => { //update UI resources })); – sumeet kumar Sep 03 '15 at 19:20
  • @sumeetkumar how could i apply it in a loop and run it every 0.20 seconds – Sven van den Boogaart Sep 03 '15 at 19:46
  • As an aside, running at 50fps with stock windows timers is going to be unreliable - the best resolution you tend to get is ~15ms. Going higher resolution can kill laptop battery lifetime. See [Why are .NET timers limited to 15 ms resolution?](http://stackoverflow.com/q/3744032/156755) and [How to: Use the High-Resolution Timer](https://msdn.microsoft.com/en-us/library/aa964692%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396) – Basic Sep 03 '15 at 20:00
  • I have received Invalid Operation when i was trying to update GUI using a separate thread and as far as update is considered 0.20sec=200 millisecond i think that should be OK as per me. – sumeet kumar Sep 03 '15 at 20:08
  • Your questions says `0.02 seconds`... As to updating the UI from a background thread, it's not possible directly but you can [use `Dispatcher.Invoke()`](http://stackoverflow.com/a/1644254/156755) to pass calls to the main thread and they'll be processed when the main thread finishes whatever else it's doing. You won't get a perfectly consistent refresh rate, but it will be close. The only way to get constant framerate is to spin wait = high cpu usage, but I don't think that should be neccessary. – Basic Sep 03 '15 at 22:12
  • Delete all that and use proper XAML and DataBinding... there's no "update" nor "render" in WPF, there's only XAML, databinding and MVVM. If these practices do not suit your needs, maybe you need a different framework. – Federico Berasategui Sep 03 '15 at 22:31
  • @HighCore The Update and Render are functions in my game class. It is only to test some design patterns, we need to use a game pattern were we update some object, check for colissions etc than update the view (very simplified explenation) so if i could just update the view that would be enough. The solution as I have it works but as i said before feels hacky. – Sven van den Boogaart Sep 03 '15 at 22:34
  • `update some object, check for colissions etc than update the view` - Again, you don't "update the view" (whatever that means) in WPF, you use DataBinding to connect the UI to a proper object model. Maybe you need a different framework... – Federico Berasategui Sep 03 '15 at 22:36
  • @HighCore I know it isn't ment to be used like that but that dosnt meen it can't and shouldn't for testing a pattern it's perfectly fine imho. As i said before everything works exactly as i want except the update of the view is improvised.. – Sven van den Boogaart Sep 03 '15 at 22:38
  • @SvenB I can only repeat what I said [here](http://stackoverflow.com/a/21884638/643085). – Federico Berasategui Sep 03 '15 at 22:42
  • @HighCore I hear what your saying and i agree i guess il use c++ for testing some patterns in the future again. i thought it would be faster to do it in wpf when needing a design. – Sven van den Boogaart Sep 03 '15 at 22:46
  • @SvenB why not just use the Canvas and Javascript? – Canvas Sep 03 '15 at 23:04
  • @Canvas im not that experienced in javascript but as far as i know making patterns with nested objects etc is much easyer in c++ or c#, java than in javascript – Sven van den Boogaart Sep 03 '15 at 23:15

1 Answers1

0

Use the CompositionTarget.Rendering event to update your Canvas control. This event is fired each time WPF renders a frame. This is a more traditional method of updating your UI on a loop.

CompositionTarget.Rendering += DoUpdates;

private void DoUpdates(object sender, EventArgs e)
{
    // Update canvas
}
Glen Thomas
  • 10,190
  • 5
  • 33
  • 65